1、什么是原型链?JavaScript的每个实例对象都有一个私有属性(称为__proto__)指向上层的对象,上层的对象指向下一层的对象,以此类推,直到__proto__属性为null,最后这个对象是对象。这种通过__proto__属性链接对象的方法称为原型链。varo={a:1};//原型链如下://o--->Object.prototype--->nullvara=["yo","whadup","?"];//a--->Array.prototype--->Object.prototype--->nullfunctionf(){return2;}//原型链如下://f--->Function.prototype--->Object.prototype--->nullfunctionf(){this.a=1;this.b=2;}leto=newf();f.prototype.b=3;f.prototype.c=4;//原型链如下//{a:1,b:2}--->{b:3,c:4}--->Object.prototype--->null2.如何使用它?1.Object.getPrototypeOf()和Object.setPrototypeOf()从ECMAScript6开始,可以通过Object.getPrototypeOf()和Object.setPrototypeOf()访问器访问__proto__属性。函数f(){this.a=1;this.b=2;}leto=newf();//1.为f的上层对象添加新属性(推荐使用此方法添加新属性)f.prototype.b=3;f.prototype.c=4;//2.查看上层对象的属性console.log(Object.getPrototypeOf(o));//3.这样设置上层对象的属性会覆盖所有Old属性,慎用console.log(Object.setPrototypeOf(o,{e:5}));//4.查看新的上层对象属性console.log(Object.getPrototypeOf(o));2.Prototype和Object.getPrototypeOf功能相同,都是用来访问原型属性,不同的是:prototype用于类,Object.getPrototypeOf()用于实例;shared:所有实例都可以访问,新的原型属性。functionA(){this.a="a";}letaIns=newA();//1,一个是type,一个是instanceconsole.log(A.prototype);console.log(Object.getPrototypeOf(aIns));letbIns=newA();//2.共享:所有实例都可以访问新添加的原型属性A.prototype.b="b";console.log(Object.getPrototypeOf(aIns).b);console.log(Object.getPrototypeOf(bIns).b);varo=newFoo();//上面的代码是让JavaScript执行下面的代码varo=newObject();o.__proto__=Foo.prototype;Foo.call(o);3.hasOwnProperty在访问一个对象的属性时,不仅会在对象上查找,还会查找原型链上的所有对象,最后判断该属性是否存在。hasOwnProperty是JavaScript中唯一不遍历原型链的方法。constobject1={};object1.property1=42;console.log(object1.hasOwnProperty('property1'));//预期输出:trueconsole.log(object1.hasOwnProperty('toString'));//预期输出:false4,undefined没有被赋值的属性是undefined,所以无法通过undefined判断一个属性是否存在。3.继承继承也是基于原型链的特性。ECMAScript6引入了class关键字来实现类对象,但是类对象也是基于原型链的。1.Object.create使用Object.create创建继承的对象。vara={a:1};//a--->Object.prototype--->nullvarb=Object.create(a);//b--->a--->Object.prototype--->nullconsole.log(b.a);//1(继承)varc=Object.create(b);//c--->b--->a--->Object.prototype--->nullvard=Object.create(null);//d--->nullconsole.log(d.hasOwnProperty);//undefined,因为d没有继承Object.prototype4.其他1.性能尝试访问不存在的属性遍历整个原型链时,在原型链上查找属性很耗时,有副作用性能上。2.扩展内置原型的错误做法会破坏封装。这不是一个好的解决方案。使用扩展内置原型的唯一原因是为了支持JavaScript引擎的新特性,例如Array.forEach。不应扩展本机原型,除非它是为了与新的JavaScript功能兼容。5.参考文档详解JavaScript继承和原型链(prototype)
