继承是 00语言 中的一个最为人津津乐道的概念。许多 00语言 都支持两种继承方式:接口继承和实现继承。接口继承只继承方法签名,而实现继承则继承实际的方法。如前所述,由于函数没有签名,在 ECMAScript 中无法实现接口继承。ECMAScript 只支持实现继承,而且其实现继承主要是依靠原型链来实现的。
function superType() { superType.prototype.name = 'Anani'; superType.prototype.getYear = function() { console.log(2018); } }
而实例都包含一个指向原型对象的内部指针。当我们让原型对象等于另一个类型的实例,此时的原型对象将包含一个指向另一个原型的指针,相应地,另一个原型中也包含着一个指向另一个构造函数的指针。假如另一个原型又是另一个类型的实例,那么上述关系依然成立,如此层层递进,就构成了实例与原型的链条。这就是原型链的基本概念。
原型链存在的问题:1、包含引用类型值的原型属性会被所有实例共享。2、在创建子类型的实例时,不能向超类型的构造函数中传递参数(其实是有办法在不影响所有对象实例的情况下,给超类型的构造函数传递参数)。
function SuperType() { this.property = 'something'; } SuperType.prototype.getSuperValue = function() { return this.property; }; function SubType() { this.subProperty = 'other something'; } SubType.prototype = new SuperType(); SubType.prototype.getSubValue = function() { return this.subProperty; }; var instance = new SubType(); alert(instance.getSuperValue());
所有引用类型默认都继承了 Object,而这个继承也是通过原型链实现的。需要注意的是:所有函数的默认原型都是 Object 的实例,因此默认原型都会包含一个内部指针,指向 Object.prototype 。这也正是所有自定义类型都会继承 toString()、valueOf() 等默认方法的根本原因。
每个对象都有一个隐藏的属性:__proto__,可称为隐式原型,其指向创建该对象的函数的 prototype。但是 Object.prototype 是一个特例——它的 __proto__ 指向的是 null。