JavaScript进阶之原型链
对象
1 function f1(){ 2 }; 3 typeof f1 //"function"函数对象 4 5 6 var o1 = new f1(); 7 typeof o1 //"object"普通对象 8 9 var o2 = {}; 10 typeof o2 //"object"普通对象
javascript中将对象分为普通对象和函数对象。
使用函数对象可以创建普通对象,普通对象没法创建函数对象。
凡是通过new function创建的对象都是函数对象,其他都是普通对象(通常通过object创建),可以通过typeof来判断。
原型对象(prototype)
prototype
prototype有原型、蓝本的意思,只有函数对象才会有原型(prototype)。
所谓原型,就是函数用来创建实例(普通)对象的蓝本(原型)。
每个原型都有一个 constructor 属性指向关联的构造函数。
__proto__
每一个javascript对象(除了 null )都具有的一个属性,叫__proto__,这个属性会指向该对象的原型(prototype)。
constructor
构造函数,即用来创建实例的函数,即关联的函数对象本身。
验证
在火狐或者谷歌浏览器控制台中新建一个普通对象,查看他的属性。
1 var o = {}; 2 console.log(o.prototype); //undefined 普通对象没有prototype属性 3 console.log(o instanceof object); //true o是object的实例 4 console.log(o.__proto__ === object.prototype) //true o的__proto__指向object的prototype 5 console.log(object === object.prototype.constructor) //true object.prototype.constructor指向object本身 6 console.log(object.prototype.constructor) //function object() 函数对象原型的构造函数指向这个函数 7 console.log(object.prototype.__proto__); //null object.prototype的__proto__为null,为原型链终点
新建一个函数对象,查看他的属性。
1 function demo() { }; 2 var f1 = new demo(); 3 console.log(f1.prototype); //undefined 通过函数对象穿创建的是普通对象,demo本身是函数对象 4 console.log(f1 instanceof demo); //true f1是demo的实例 5 console.log(f1.__proto__ === demo.prototype); //true 6 console.log(demo === demo.prototype.constructor);//true 7 console.log(demo.prototype.__proto__ === object.prototype);//true demo原型的__proto__指向object的原型prototype 8 console.log(object.prototype.__proto__); //null
原型的重要功能就是用作继承。
原型链(prototype chain)
javascript中,每个对象都会在内部生成一个__proto__ 属性,当我们访问一个对象属性时,如果这个对象不存在就回去__proto__ 指向的对象里面找,一层一层找下去,这就是javascript原型链的概念。
提升:
- 在原型链上查找属性比较耗时,对性能有副作用,这在性能要求苛刻的情况下很重要。另外,试图访问不存在的属性时会遍历整个原型链。
- 遍历对象的属性时,原型链上的每个可枚举属性都会被枚举出来。要检查对象是否具有自己定义的属性,而不是其原型链上的某个属性,则必须使用对象从object.prototype继承的 hasownproperty 方法。(使用 for in 遍历对象时推荐总是使用 hasownproperty 方法)
继承
javascript 并没有其他基于类的语言所定义的“方法”。在 javascript 里,任何函数都可以添加到对象上作为对象的属性。函数的继承与其他的属性继承没有差别。
继承意味着复制操作,在java和c#中,继承是完全复制生成新的对象。然而 javascript 默认并不会复制对象的属性,相反,javascript 只是在两个对象之间创建一个关联,这样,一个对象就可以通过委托访问另一个对象的属性和函数,所以与其叫继承,委托的说法反而更准确些。
结论
在编写使用它的复杂代码之前,理解原型继承模型是至关重要的。此外,请注意代码中原型链的长度,并在必要时将其分解,以避免可能的性能问题。此外,原生原型不应该被扩展,除非它是为了与新的javascript特性兼容。
参考文档: https://www.jb51.net/article/123976.htm
https://github.com/mqyqingfeng/blog/issues/2
https://developer.mozilla.org/zh-cn/docs/web/javascript/inheritance_and_the_prototype_chain
上一篇: python自动化之re模块详解