首先列出经常会听到的属性,之后来说明它们之间的关系,再进一步解释如何通过这些属性构建JS的层层继承。
属性
proto所有的对象都拥有这个属性,这个属性是继承的关键。
prototype是函数独有的一个属性,在使用new来构建新对象时,它与新对象的proto属性有关。
__proto属性与prototype属性都是对象。
这些属性本身没有什么特别,但它们之间的关系却比较复杂,下面加上代码的印证,说清楚他们之间的关系。
基础实现
这里新建一个函数,函数也是对象,它有自己的属性,我们为它的prototype(原型链)属性添加一个方法introduce,之后通过new方法新建一个子类,输出子类car的name属性,调用子类的方法
function Car (name) {
this.name = name;
}
Car.prototype.introduce = function () {
console.log('Hello, my name is: ' + this.name);
}
var car = new Car('Alice');
console.log(car.name);
car.introduce();
继承的实现
我们学习面向对象的编程语言,很多时候是为了提高效率和正确性,而继承是实现这两点的关键,既然需要实现继承,那么来JS中是如何实现的。
JS创造了prototype属性在通过函数构造子类时生成proto属性,通过proto_属性来连接子类和父类。
于是,我们先从prototype属性说起,先明确一点,这个属性是函数特有的,这个属性的作用是为了在使用new来构造新对象实例时,可以让对象实例共享一些函数。
对于上面的代码,在使用Car这个构造函数构建的对象实例后,所有的新构建的对象实例都会拥有方法introduce。
理解了这里,我们来整体看一次。
先定义一个构造函数Car,之后为其原型添加方法,接着使用new标识符通过构造函数来新建一个对象。等等,这里需要听一下,为什么一个new可以有这么大的作用,这里面发生了什么?
new
那我们先说说new,它的确执行了好几个步骤,才产生了一个新对象。
- 首先新建一个空对象car,每个对象在创建之后,就会拥有一个proto隐藏属性,这个属性会原本指向Object属性的原型对象,可以通过下面的代码一窥究竟
var a = {}
a.__proto__
Object {}
__defineGetter__:__defineGetter__()
constructor:Object()
...
a.__proto__ === Object.prototype
// true
- 改变proto属性的指向,将它指向Car函数的prototype属性
- 让Car函数内部的this指向新建的对象car
- 执行构造函数,构造函数也是函数,但这个构造函数并没有返回任何值,但在它执行的过程中,由于this是指向新对象car的,所以它会为car的name属性赋值。执行完毕后,car对象会拥有name属性。
原型链上的方法
由于现在car.proto引用了Car.prototype引用的对象,那么他们会共享属性。
网友评论