ES5/ES6原型链与继承
2017-12-11 本文已影响160人
4dfab65f4d18
原型链相关.pngES5最经典的寄生组合式继承
注意
如果A.prototype没有constructor,只要B.prototype的原型对象是A.prototype,则b instance of A就为true
ES6和ES5继承的代码实现
//ES5继承
function Super(name){
this.name=name
this.colors=[1,2,3]
}
Super.prototype.sayName=function(){
alert(this.name)
}
function Sub(name,age){
Super.call(this,name)//显式传入this作为显示调用者调用父类构造函数
this.age=age
}
Sub.prototype=Object.create(Super.prototype,{
constructor:{
value:Sub
}
})//避免调用父类的构造函数
Sub.prototype.sayAge=function(){
alert(this.age)
}
//ES6继承
class Super{
constructor(name){
this.name=name
}
sayName(){
alert(this.name)
}
static haha(){
alert(this.hahatext)//Super函数对象的静态属性
}
}
Super.hahatext="dingxu1"
class Sub extends Super{
constructor(name,age){
super(name)//先实例化父构造函数,在更改this的指向,super()之后才有了this!
this.age=age
}
sayAge(){
alert(this.age)
}
}
Sub.hahatext="dingxu2"
Super.haha()//dingxu1
Sub.haha()//dingxu2
/***********************************************/
Sub.__proto__ === Super // true 作为一个对象,子类(Sub)的原型(__proto__属性)是父类(Super)
Sub.prototype.__proto__ === B.prototype // true 作为一个构造函数,子类(Sub)的原型对象(prototype属性)是父类的原型对象(prototype属性)的实例。
- ES5 是先新建子类的实例对象this,再将父类的属性添加到子类上,由于父类的内部属性无法获取,导致无法继承原生的构造函数。比如,Array构造函数有一个内部属性[[DefineOwnProperty]],用来定义新属性时,更新length属性,这个内部属性无法在子类获取,导致子类的length属性行为不正常。
- ES6 允许继承原生构造函数定义子类,因为 ES6 是先新建父类的实例对象this,然后再用子类的构造函数修饰this,使得父类的所有行为都可以继承。下面是一个继承Array的例子。
class MyArray extends Array{
constructor(...args){
super(...args)
}
}
var arr=new MyArray()
arr[0]=12
arr.length
arr.length=0
arr[0]
extends关键字不仅可以用来继承类,还可以用来继承原生的构造函数。因此可以在原生数据结构的基础上,定义自己的数据结构。
class VersionedArray extends Array {
constructor() {
super();
this.history = [[]];
}
commit() {
this.history.push(this.slice());
}
revert() {
this.splice(0, this.length, ...this.history[this.history.length - 1]);
}
}
var x = new VersionedArray();
x.push(1);
x.push(2);
x // [1, 2]
x.history // [[]]
x.commit();
x.history // [[], [1, 2]]
x.push(3);
x // [1, 2, 3]
x.history // [[], [1, 2]]
x.revert();
x // [1, 2]
注意,继承Object的子类,有一个行为差异。
class NewObj extends Object{
constructor(){
super(...arguments);
}
}
var o = new NewObj({attr: true});
o.attr === true // false
上面代码中,NewObj继承了Object,但是无法通过super方法向父类Object传参。这是因为 ES6 改变了Object构造函数的行为,一旦发现Object方法不是通过new Object()这种形式调用,ES6 规定Object构造函数会忽略参数。