关于javascript:JS-常用继承

罕用的继承形式

1:原型链继承

function Child(){
    this.age="10";
}
function Father(){
    this.name="father";
    this.friends=['a','b'];
}
Father.prototype.sayName=function(){
    console.log(this.name);
}
Child.prototype=new Father();
Child.prototype.constructor=Child;
var c1=new Child();
var c2=new Child();
c2.friends.push('c');

/**
顾名思义通过原型prototype对象进行继承,原型链向上查找公共属性办法.
Child.prototype指向了Father实例
毛病:
1:无奈向父类传递参数用于结构。
2:父类的name,firends公有属性,都成子类原型私有属性。
c2.friends.push('c');执行后
c1.firends也被批改 
c2.friends==c1.friends==['a','b','c']
*/

2:构造函数继承

function Child(data){
    this.age="10";
    Father.call(this,data)
}
function Father(data){
    this.name=data.name;
    this.friends=data.friends;
    this.sayName=function(){
        console.log(this.name)
    }
    console.log("被执行了")
    
}
Father.prototype.showFriends=function(){
    console.log(this.showFriends);
}
var c1=new Child({
    name:'c1',
    friends:['a','b']
})
var c2=new Child({
    name:'c2',
    friends:['c','d']
})
c1.friends.push('x')
c2.friends.push('y')

/**
通过call|apply进行继承(属性拷贝),与prototype没有关系
能够向子类传递结构参数,子类继承的父类属性独立.
实现所有属性办法独享.
毛病:
1:雷同公共办法sayName没抽离,
所有子类都有本人独立的sayName,(c1.sayName===c2.sayName)false
*/

3:原型继承+call继承(组合继承)

function Child(data){
    Father.call(this,data)
}
function Father(data){
    this.name=data?data.name:"father";
    this.friends=data?data.friends:[];
    console.log("Father构造函数执行了")
}
Father.prototype.showFriends=function(){
    console.log(this.friends)
}

Child.prototype=new Father();
Child.prototype.constructor=Child;

var c1=new Child({
    name:'c1',
    friends:['a','b']
})
var c2=new Child({
    name:'c2',
    friends:['c','d']
})
c1.friends.push('x')
c2.friends.push('y')
c1.showFriends()
c2.showFriends()

/**
公有属性构造函数继承,公共属性办法原型链实现。
毛病:
1:调用了两次父类构造函数,生成了两份实例
Father.call,Child.prototype=new Father();
*/

4:寄生式继承

function createObj(o){
    function F(){
    }
    F.prototype=o;
    return new F();
}

function Child(data){
    Father.call(this,data)
}

function Father(data){
    this.name=data?data.name:"father";
    this.friends=data?data.friends:[];
    console.log("Father构造函数执行了")
}

Father.prototype.showFriends=function(){
    console.log(this.friends)
}
Father.prototype.likes=['吃','睡'];


Child.prototype=createObj(Father.prototype);
Child.prototype.constructor=Child;
Child.prototype.childLikes=function(){
    console.log('aaa')
}
var c1=new Child({
    name:"c1",
    friends:['a','b']
})
var c2=new Child({
    name:"c2",
    friends:['c','d']
})
var f1=new Father({
    name:"f1",
    friends:['e','f']
})
c1.friends.push('x')
c2.friends.push('y')
console.log(c1,c2);

/**
应用两头空对象F来连接子类与父类,子类原型指向F实例
F.prototype==Father.prototype,F没有公有属性因而new开销比拟小。
*/

5:Class继承

class Father{
    constructor(data){
        this.name=data?data.name:"father";
        this.friends=data?data.friends:[];
    }
    showFriends(){
        console.log(this.friends)
    }
}
class Child extends Father{
    constructor(data){
        super(data);
    }
}
var c1=new Child({
    name:'c1',
    friends:['a','b']
})
var c2=new Child({
    name:'c2',
    friends:['c','d']
})
c1.friends.push('x')
c2.friends.push('y')
console.log(c1,c2)
/**
和寄生式继承成果一样,简洁语义更好。
子类构造函数必须先调用一次super
*/

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理