原型链简介
JavaScript不包含传统的继承,因此引入原型链模型模拟继承功能。
__proto__属性
__proto__属性是隐藏属性,不应该出现在日常的编码中,这里只是为了理解原型链提到这个属性。
下面是例子
var bar;
console.log(bar.attr);
//undefined
上面代码的工作原理是
- 寻找定义在
bar上的attr属性,若找到则返回,若找不到,继续 - 寻找定义在
bar.__proto__上找attr属性,若找到则返回,若找不到则继续 - 寻找定义在
bar.__proto__.__proto__上的attr属性,若找到则返回,若找不到则继续 - 直到找到的
bar.__proto__....__ptoto__为null,若还未找到,则返回undefined
理解JavaScript中了寻找属性的流程,我们来看实例化一个类时new做了些什么。
new关键字与prototype
new一个对象的实际过程如下
var bar = new Bar();
// function new () {
// var bar = {};
// bar.__proto__ = Bar.prototype;
// Bar.apply(bar, arguments);
// return bar;
// }
- 将Bar的
prototype对象直接赋值给bar的__proto__ - 以bar为this,apply运行Bar这个函数
这么做了的结果是**定义在Bar.prototype上的属性和方法将能被bar访问到!**比如:
function Bar () {
this.bar = 'bar';
}
Bar.prototype.attr = 'value';
Bar.prototype.getAttr = function() { return this.attr };
var bar = new Bar();
bar.getAttr();
// bar中不包含getAttr,但是bar.__proto__包含这个函数,执行成功。
// value
这里着重理解bar.__proto__ = Bar.prototype;正因为在new的过程中,bar的__proto__被赋值为Bar的prototype,所以定义在Bar的prototype上的属性和方法能被bar访问到。这样,达到了Bar作为类,实例化了一个bar对象的目的。
PS: 这里的赋值实际上是引用,意思是bar的__proto__和Bar的prototype指向同一个对象,其中给一个改变了,另一个也跟着改变。要理解这个,需要看看JavaScript中引用和赋值的问题。
多级继承例子
下面介绍多级继承的例子
var Foo = function() {
this.foo = 'foo';
}
Foo.prototype.isFoo = true;
var Bar = function() {
Foo.apply(this, arguments);
this.bar = 'bar';
}
Bar.prototype.__proto__ = Foo.prototype;
Bar.prototype.isBar = true;
var bar = new Bar();
console.log(bar);
//{bar: 'bar'}
console.log(bar.foo);
//**bar.__proto__隐含了属性foo**
//'foo'
console.log(bar.isFoo);
//**bar.__proto__.__proto__隐含了属性isFoo**
//true
求补充,直接评论