JavaScript中的继承

JavaScript中的继承通过原型链来实现:把父类的实例赋值给子类的原型,具体实现有以下几种类型

1.原型链继承

function SuperType(){
    this.colors = ['black','white','yellow'];
}
function SubType(){
}
SubType.prototype = new SuperType();
//等价于SubType.prototype.colors = ['black','white','yellow']
var instance1 = new SubType();
instance1.colors.push('red');
var instance2 = new SubType();
//会查找SubType.colors
console.log(instance2.colors);//输出["black", "white", "yellow", "red"]

这种方式会导致SubType的所有实例共享colors,也无法像父类的构造函数传递参数

2.借用构造函数实现继承

function SuperType(){
    this.colors = ['red','yellow','green'];
}
function SubType(){
    SuperType.call(this);
}
var instance1 = new SubType();
instance1.colors.push('black');
console.log(instance1.colors);
var instance2 = new SubType();
console.log(instance2.colors);//输出["red", "yellow", "green"]

优点:可以向父类函数传递参数,通过call方法来调用父类的构造函数。而且实例之间的colors是分开的
缺点:对于属性,分开是好事,但是对于方法,则应该公用,这种继承无法做到函数复用

3.组合继承

function SuperType(name){
    this.name = name;
    this.colors = ['red', 'blue', 'green'];
}
SuperType.prototype.sayName = function(){
    console.log(this.name);
}
function SubType(name, age){
    //继承属性
    SuperType.call(this, name);

    this.age = age;
}
//继承方法
SubType.prototype = new SuperType();
SubType.prototype.constructor = SubType;//这一句有什么作用?判断对象类型除了用instanceof外,还可以用constructor,此处为了保证可以用constructor,所以把constructor复原
SubType.prototype.sayAge = function(){
    console.log(this.age);
}

var instance1 = new SubType('mao', 22);
instance1.colors.push('black');
console.log(instance1.colors);
instance1.sayName();
instance1.sayAge();

var instance2 = new SubType('madong',23);
console.log(instance2.colors);
instance2.sayName();
instance2.sayAge();

console.log(instance1.colors);
instance1.sayName();
instance1.sayAge();

在实例中定义属性,在原型上定义方法,解决了方法不共用的问题,比较常用

4.原型式继承

var person = {
    name: 'mao',
    friends: ['node', 'cnpm', 'jquery', 'react']
};
var anotherPerson = Object.create(person);
var anotherAnotherPerson = Object.create(person);
anotherPerson.name = 'mao1';
anotherPerson.friends.push('css');
//person,anotherPerson,anotherAnotherPerson共享friends
console.log(anotherAnotherPerson.friends);

利用原生方法Object.create()来对person进行浅复制,实例之间共享属性

5.寄生式继承

function createAnother(original){
    var clone = Object.create(original);
    clone.sayHi = function(){
        console.log('hi');
    }
    return clone;
}
var person = {
    name: 'mao',
    friends: ['node', 'cnpm', 'jquery', 'react']
};
var anotherPerson = createAnother(person);
anotherPerson.sayHi();

创建了一个函数来封装继承过程

6.寄生组合式继承

function inheritPrototype(subType, superType){
    var prototype = Object.create(superType.prototype);
    prototype.constructor = subType;
    subType.prototype = prototype;
}
function SuperType(name){
    this.name = name;
    this.colors = ['red', 'blue', 'green'];
}
SuperType.prototype.sayName = function (){
    console.log(this.name);
}
function SubType(name, age){
    SuperType.call(this,name);
    this.age = age;
}
inheritPrototype(SubType, SuperType);
SubType.prototype.sayAge = function(){
    console.log(this.age);
}
var instance1 = new SubType('mao', 22);
var instance2 = new SubType('mao2', 22);
instance1.colors.push('yellow');
console.log(instance2.colors);//不受影响
console.log(instance1.sayName==instance2.sayName);//true

这是比较好的方式,实例属性分开,实例方法共享,另外相比于组合继承,只调用了一次父类的构造函数

总结:
继承的方式不少,其实只要理解和掌握第六种,寄生组合式继承就可以了,其他的自然就懂。理解这些继承,要牢牢记住访问实例属性和方法的过程,先在实例中找,再去原型上找,并且要注意,实例.属性 = xxx; 这样子会导致在实例上创建属性,从而屏蔽原型上的属性,如果实例.属性是在等号的右边,那么还是查找而已。

来源于《JavaScript高级程序设计》

你可能感兴趣的:(JavaScript,javascript,继承)