了解JS继承特性我们必须了解原型链:
JavaScript 对象有一个指向一个原型对象的链。 当试图访问一个对象的属性时,它不仅仅在该对象上搜寻,还会搜寻该对象的原型, 以及该对象的原型的原型,依此层层向上搜索,直到找到一个名字匹配的属性或到达原型链的末尾, 这就是原型链.
概念
JavaScript的所有对象,都有自己的继承链。也就是说,每个对象都继承另一个对象,该对象称为“原型”(prototype)对象。只有null除外,它没有自己的原型对象。
原型对象的重要性在于,如果A对象是B对象的原型,那么B对象可以拿到A对象的所有属性和方法。Object.getPrototypof方法用于获取当前对象的原型对象。
通过对象__proto__属性来继承
var obj = {};
var a = {};
obj.__proto__ = a;
这里将obj对象原型设为a对象
var a = {x: 99};
var b = {__proto__: a};
b.x // 99
上面的示例代码, b对象通过__proto__属性,将自己的原型对象设为a对象,因此b对象可以拿到a对象的所有属性和方法。 b对象本身并没有x属性,但是JavaScript引擎通过__proto__属性,找到它的原型对象a,然后读取a的x属性。
var a = { x: 1 };
var b = { __proto__: a };
var c = { __proto__: b };
c.x // 1
这里要注意的是,在原型链寻找某个属性,对性能是有影响的。 寻找的属性在越上层的原型对象,对性能的影响越大。如果寻找某个不存在的属性,将会遍历整个原型链。
原型链继承
这里使用了匿名闭包的方式避免全局污染
(function(){
function Foo(n,a){
this.name=n;
this.age=a;
this.action=function(){
console.debug(this.name,this.age);
}
}
function Bua(){
Foo.apply(this,arguments); //Bua继承了Foo的属性和方法
}
Bua.prototype=new Foo(); //Bua继承Foo的原型(constructor丢失)
Bua.prototype.constructor=Bua; //重新定义Bua函数的constructor
})();
这里Foo函数的this指针指向了Bua函数,结果就是调用Bua函数相当于调用了Foo(最终实现Bua函数继承了Foo函数的属性和方法), 但是会造成Bua函数的constructor丢失;原因是因为Bua的原型被new Foo()这个实例给重新定义了.而new Foo()这个实例没上没有constructor. 解决办法就是从新定义Bua函数的constructor.
ES6的继承
Object.create()部分浏览器不支
以上一个为例
Object.create(Foo.prototype,{constructor : {value:Bua}})//会返回一个新对象
Object.create(prototype, descriptors) :创建一个具有指定原型且可选择性地包含指定属性的对象;
这里要说一下prototype和__proto__的概念
prototype是函数的一个属性(每个函数都有一个prototype属性),这个属性是一个指针,指向一个对象。它是显示修改对象的原型的属性。 __proto__是一个对象拥有的内置属性(请注意:prototype是函数的内置属性,__proto__是对象的内置属性),是JS内部使用寻找原型链的属性。
总结:
1.__proto__的继承, 只是改变了原型的指向.
2.原型链继承, 缺点会产生垃圾属性和方法.
3.ES6的继承(推荐), 缺点部分浏览器不支.
评论 (0)