JS原型和原型链
原型
任何对象都有一个原型对象,这个原型对象由对象的内置属性_proto_指向它的构造函数的prototype指向的对象,即任何一个对象都是由一个构造函数创建的,每一个构造函数都有一个和它相关联的原型对象(譬如:Object()有Object.prototype,比较特殊的是Function()和Function.prototype,因为所有的函数和构造函数都是由Function()生成,所以,所有构造函数有与之相连的Function.prototype),但是不是每一个对象都有prototype,只有方法才有prototype,而普通对象没有prototype
prototype可以看作是一个指针,指向了原型对象。原型对象默认有一个属性constructor,这个属性也是一给指针,指向的是其相关联的函数。
原型对象的用途
继承,
因为p的prototype设置了一个函数对象的属性,因此普通对象在new p()时就继承了这个属性。
图解:
但是原型模式的最大问题是由于共享的特性,当k或者l中任何一个修改,另外一个也会受到影响。
所有的对象都有__proto__属性,该属性对应该对象的原型;所有的函数对象都有prototype属性,该属性的值会被赋值给该函数创建的对象的__proto__属性;所有的原型对象都有constructor属性,该属性对应创建所有指向该原型的实例的构造函数;函数对象和原型对象通过prototype和constructor属性进行相互关联
原型链
原型链的核心就是依赖对象_proto_的指向,当自身不存在的属性时,就一层层的找出对象的构造函数,直到Object时,就没有_proto_指向了。
如下题:
分析:因为fn的构造函数为Foo(),所以fn.___proto__===Foo.prototype
又由于Foo.prototype的构造函数为Obiect,所以Foo.prototype.__proto__===Object.prototype.当fn调用toString()时,由于fn中没有这个方法,于是,就到Foo.prototype中找,又没找到,继续向上层找,如果在Object.prototype中找到了就直接使用,没有找到就报错或则返回空。
属性搜索原则:
当访问一个对象的成员的时候,会先在自身找有没有,如果找到直接使用。
如果没有找到,则去原型链指向的对象的构造函数的prototype中找,找到直接使用,没有找到就返回undefined或则报错。
对象的创建方式会影响原型链(两种不同的方式)
属性隐藏
如果想要覆盖原型链上的某些属性,就可以直接在对象上创建函数以隐藏这些属性。
instanceof
用于测试构造函数的prototype属性是否出现在对象的原型链中的任何位置,用于检测constructor.prototype是否存在于参数object的原型链中。
本质上用于判断实例属于那个构造函数,实例对象的_proto_属性和构造函数的prototype属性是否指向同一个地址。
哈哈哈,未完待续...