点击蓝色“达达前端”关注我!加个“星”,每天一篇,一起学编程目录说说原型模式每个函数都有一个prototype原型属性,是一个指向对象的指针,这个对象的作用就是属性和方法可以由特定类型的所有实例共享。那么这个原型就是调用构造函数创建的对象实例的原型对象。原型对象的优点是所有对象实例共享它包含的属性和方法。从上面的代码我们可以看出构造函数是一个空函数,sayName()方法和所有的属性都直接添加到Person的prototype属性中。调用构造函数创建一个新对象,该对象将具有相同的属性和方法。但与构造函数不同的是,这个新对象的属性和方法是所有实例共享的。也就是说,person1和person2访问相同的属性集和相同的sayName()函数。只要原型对象创建了一个新的函数,它内部就会创建一个prototype属性,它指向函数的原型对象。并且所有的原型对象都会自动获得一个constructor构造函数属性,该属性指向原型属性所在函数的指针。示例:Person.protype.constructor指向Person。JavaScript对象原型所有JavaScript对象都从原型继承属性和方法。了解如何使用对象构造函数。您目前无法向现有对象构造函数添加新属性。如果要向构造函数添加新属性,则必须将其添加到构造函数。原型继承所有JavaScript对象都从原型继承属性和方法。日期对象继承自Date.prototype。数组对象继承自Arrray.prototype。Person对象继承自Person.prototype。Object.prototype位于原型继承链的顶端。Date对象、数组对象和Person对象都继承自Object.prototype。向对象添加属性和方法要求一,当您需要向给定类型的所有现有对象添加新属性或方法时。需求2,当需要向对象构造函数添加新的属性或方法时。使用原型属性JavaScript中的原型属性允许您向对象构造函数添加新的属性或方法。构造函数创建后,其原型对象会获得constructor属性。至于其他的方法,都是继承自Object。当调用构造函数创建新实例时,实例内部包含一个指针,指向构造函数。原型对象。这个指针称为原型,每个对象都有一个名为__proto__的属性。注意this指针存在于实例和构造函数的原型对象之间,而不是存在于实例和构造函数之间。可以画出并分析Person的构造函数、Person的prototype属性、Person的两个实例之间的关系结构。Person构造函数有一个原型。指向原型对象,PersonPrototype。PersonPrototype具有构造函数、姓名、年龄、工作、sayName。Person.prototype.constructor指向Person。除了构造函数属性外,原型对象还有其他后来添加的属性。Person的每个实例都有一个内部属性,只是指向Person.prototype,严格来说,它们与构造函数没有直接关系。其中一个关键点,当调用构造函数创建一个新的实例时,实例中会包含一个指向构造函数原型对象的指针,这个指针叫做[[Prototype]]。每个对象都支持属性__proto__。解释概念什么是对象?对象是属性和方法的集合,即变量和函数的封装。每个对象都有一个__proto__属性,它指向对象的构造函数的原型对象。什么是构造函数?构造函数是用于创建对象的函数。通过new关键字的方法生成对象,函数名一般大写。什么是原型对象?每个函数都有一个原型属性,它是一个指向原型对象的指针,原型对象是在定义函数时创建的。对象中的__proto__属性对象中的__proto__属性在所有实现中都是不可访问的,但是可以使用isPrototypeOf()方法来确定对象之间是否存在这种关系。person1和person2中有指向Person.prototype的指针,返回为true。ECMAScript5中添加了一个名为Object.getPrototypeOf()的新方法,它在所有支持的实现中返回[[Prototype]]的值。于是就有了如下例子:确认Object.getPrototypeOf()返回的对象其实就是这个对象的原型,使用Object.getPrototypeOf()可以很容易的得到一个对象的原型。代码在调用过程时,调用对象的某个属性时,会先从对象实例本身开始查找。如果找到具有给定名称的属性,如果找不到,则返回该属性的值。它将进行第二次查找,从指针指向的原型对象开始,在原型对象中查找具有给定名称的属性。如果在原型对象中找到具有给定名称的属性,则返回该属性的值。简单来说,解析器会问两个问题,一个是第一次找到它。第一个问题:实例person1是否具有sayName属性?第二个问题:实例person1的原型是否有sayName属性?虽然可以通过对象实例访问原型中存储的值,但是无法通过对象实例覆盖原型中的值。注意:person1的名字被一个新值掩盖了。person1.name返回的值来自对象实例;person2.name的值来自原型。访问person1.name时,在实例上搜索名为name的属性,如果存在则返回其值。访问person2.name时,如果实例上没有这个属性,就会在原型上查找,如果有name属性,则返回它的值。给对象添加一个属性,这个属性会屏蔽掉原型对象中相同的属性名。添加属性只会阻止我们访问原型对象中的那个属性,不会改变那个属性,而是访问实例对象上的属性。接下来,使用delete操作符删除实例属性,并尝试查看是否可以再次访问原型中的属性。使用delete操作符删除保存的值,恢复原型中name属性的连接。如何判断一个属性是存在于实例中,还是存在于原型中?我们可以使用hasOwnProperty()方法来判断对象实例中是否存在指定的属性。当它存在于对象实例中时,返回值为真。从上面的代码我们可以知道,通过使用hasOwnProperty()方法,我们知道什么时候访问实例属性,什么时候访问原型属性。使用in运算符in运算符用于确定可以通过对象访问给定属性并返回true。该属性是在实例上还是在原型上。同时使用hasOwnProperty()方法和In运算符,可以判断该属性是存在于对象中还是存在于原型中。以上代码用于判断属性是否存在于原型中。说明,如果可以通过对象访问该属性,则in运算符返回true,而只要实例中存在该属性,hasOwnProperty()就返回true。所以只要in运算符返回true而hasOwnProperty()返回false,就可以确定该属性是原型中的属性。要获取对象的所有可枚举实例属性,可以使用Object.keys()方法,该方法接受一个对象作为参数并返回包含所有可枚举属性的字符串数组。可以看出Object.keys()方法保存的是一个数组,循环出现。如果调用了Person的实例,则会显示该实例中的属性。如果你想让所有的实例属性都出现,不管它是否可枚举,你可以使用Object.getOwnPropertyNames()方法。返回结果包含不可枚举的构造函数属性。使用此方法以对象字面量的形式创建一个新对象。它缺少构造函数属性的指针,不再指向Person。每个函数在新建的时候,都会同时创建一个原型对象,这个对象会自动获得一个构造函数。属性。这时候constructor属性就变成了新对象的constructor属性,指向Object的构造函数,不再指向Person函数。如果想保留指向构造函数的指针,可以这样表达。这样,constructor属性将导致[[Enumerable]]属性为真。默认情况下,无法枚举原始构造函数属性。重置构造函数,使构造函数保持不可枚举。以上代码仅适用于兼容ESMAScript5的浏览器。可以访问friend.sayHi()调用。原因是实例和原型之间的松散连接关系。实例和原型之间的连接只是一个指针,而不是一个副本,所以你可以在原型中找到想要的属性并返回存储在那里的函数。从上面的代码来看,首先,创建一个Person的构造函数,一个空函数,其次,创建一个Person的实例,第三,在调用friend.sayName()函数时,重写其原型对象。错误。因为friend指向的是Object的构造函数,而不是指向Person函数。原型模式的重要性可以从Array.prototype中的sort()方法和Sting.prototype中的substring()方法中看出。基本包装类型String以上代码不建议进行此操作。引用类型值的属性使用构造函数模式和原型模式构造函数模式用于定义实例属性,而原型模式用于定义方法和共享属性。通过上面的代码我们可以知道,实例属性是在构造函数中定义的,所有实例共享的属性构造函数和方法sayName()都是在原型中定义的。向person1添加内容不会影响person2,因为它们引用不同的数组。一种使用组合的构造函数和原型模式来定义应用程序类型或创建自定义类型的方法。上述代码的意思是,如果原型不存在,只会将sayName()方法添加到原型中。ParasiticConstructorModeInheritance,关于继承,有两种继承方式,接口继承和实现继承。接口继承只继承方法签名,而实现继承继承实际的方法。PrototypePerson.prototype,constructor属性:Person.prototype.constructor===Person,__proto__属性中:Person.prototype.__proto__==Object.prototypeconstructor,prototype属性指向其原型对象,constructor属性指向功能。Person.constructor===Function__proto__属性:Person.__proto__===Function.prototype当通过字面量方法创建对象时,它的原型是Object.prototype,我们不能直接访问内置属性[[Prototype]],但是我们可以通过Object.getPrototypeOf()或者对象__proto__来获取对象的原型。创建对象的方法是使用Object.create()。这个方法会使用你传入的对象作为创建对象的原型。什么是原型链?因为__proto__是任何对象的属性,而js中的一切都是对象,所以会形成一个__proto__链。对__proto__的递归访问最终必须结束,值为null。js引擎在查找对象的属性时,首先会检查对象本身是否存在该属性。如果不存在,则在原型链中查找,但不会查找自己的原型。继承的主要思想是利用原型链,这是实现继承的主要方法,利用原型让一个引用类型继承另一个引用类型的属性和方法。即原型对象的构造函数指向构造函数,实例对象通过__proto__指向原型对象。层层追溯,所有对象的原型最终都可以追溯到Object.prototype,也就是Object构造函数的prototype属性。也就是说,所有对象都继承了Object.prototype属性。那么Object.prototype对象有它的原型吗?是的,Object.prototype的原型是Null。由于Null没有属性,它是原型链的末端。JavaScript引擎要读取一个对象中的某个属性,首先会去寻找这个对象本身的属性,如果找不到就去它的原型,如果还是找不到就去原型的原型找到它。当到达最顶层的Object.prototype,如果还没有找到,会返回Undefined。我做了一个示意图如下:当一个对象调用了一个本身不存在的属性或方法时,它会去与自身[proto]相关联的前身[prototype]对象中寻找。如果没有找到,就会到prototype原型[proto]相关的前辈[prototype]上去寻找。以此类推,直到找到属性或方法或Undefined,这就是所谓的原型链。总结:每次创建一个函数,该函数都会自动拥有一个原型属性,它是一个指向对象的指针,称为原型对象。原型对象默认有一个名为constructor的属性,它也是指向其关联的构造函数的指针。调用构造函数生成的实例对象有一个指向原型对象的内部属性,它的实例对象可以访问原型对象上的所有属性和方法。每个构造函数都有一个原型对象,原型对象包含一个指向构造函数的指针,实例包含一个指向原型对象的内部指针。实例可以通过内部指针访问原型对象,原型对象可以通过构造函数找到构造函数。函数中有原型,对象中有__proto__。原型是函数特有的属性。__proto__是每个对象都具有的属性。但是,__proto__不是规范属性,只有部分浏览器实现了该属性。对应的标准是[[Prototype]]大多数情况下,__proto__可以理解为“构造函数的原型”,即:__proto__===constructor.prototype。__proto__的指向取决于对象的创建方式。构造函数实例,封装的函数,如果通过new操作符调用,就是构造函数,如果不通过new操作符调用,就是普通函数。函数Person(object)有一个属性原型指针,指向原型对象,Person.prototype原型对象本质上也是一个对象。它有一个属性构造函数指针,指向Person函数对象。实例对象person1有一个属性[[Prototype]](内部属性,chrome和firefix,这个属性在Safari中叫做__proto__)指向原型对象。通过实例对象的构造函数可以访问构造函数,使用代码person1.constructor可以访问构造函数,但构造函数的本质是原型对象上的一个属性。所有对象都有valueOf和toString方法的原因是它们继承自Object.prototype。在整个原型链上搜索属性会对性能产生影响。原型对象越高,对性能的影响越大。如果要查找一个不存在的属性,则会遍历整个原型链。js中万物皆对象,但也区分了普通对象和函数对象。通过newFunction()出来的是一个函数对象。普通对象的构造函数是Object,函数对象的构造函数是Function。函数原型是一个空函数。每个对象都有一个__proto__属性,但只有函数对象有一个原型属性。☆END☆参考文档来源:《JavaScript 高级程序设计》加群前端交流群扫码备注加群-技术领域-城市-名称目前文章内容涉及前端知识点,包括Vue、JavaScript、数据结构与算法,实战演练,Node全栈前端技术紧跟行业发展,将web前端领域和网络原理以通俗易懂的方式呈现给小伙伴。更多信息请到达达前端网站学习:www.dadaqianduan.cn推荐阅读1.你对这个了解多少,new,bind,call,apply?那我告诉你2.为什么要学JavaScript设计模式,因为它是核心3.一篇文章带你走进JavaScript中的闭包和高级函数4.大厂HR面试ES6深度面试题的知识点感受那这篇文章对你有帮助吗?请分享给更多人关注“达达前端”,加star提升前端技能。这是一种品质和态度公众号
