JavaScript 继承

本文深入探讨JavaScript中六种常见的继承模式,包括原形链、借用构造函数、组合继承、原形式、寄生式及寄生组合继承,并提供详细的代码示例。重点介绍了寄生组合继承的优点及其实现细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

寄生组合继承称为完美继承(其他继承方式都有缺陷)

以下为6种继承的简单写法:
(包括:原形链、借用构造函数、组合继承、原形式、寄生式、寄生组合式6种继承)

//父类
function Parent(name) {
    this.name = name;
}
Parent.prototype.alertHi = function () {
    alert("Hi");
};

//原形链继承
function Child1() {}
Child1.prototype = new Parent();

//借用构造函数继承
function Child2(name) {
    Parent.call(this,name);
}

//组合式继承
function Child3(name) {
    Parent.call(this,name);
}
Child3.prototype = new Parent();
Child3.prototype.constructor = Child3;

//原形式继承
var Child4 = Object.create(Parent);

//寄生式继承
function createChild(child) {
    var clone = Object(child);
    clone.sayHello = function () {
        alert("Hello");
    };
    return clone;
}
var Child5 = createChild(Person);

//寄生组合式继承
var Child6 = function (name) {
    Parent.call(this,name);
};
function inheritPrototype(subType,superType) {
    var prototype = Object(superType.prototype);
    prototype.constructor = subType;
    subType.prototype = prototype;
}
inheritPrototype(Child6,Parent);

以下为6种继承的详细写法。

原形链继承

//原形链继承
//父类
function Parent() {
    this.flag = true;
}
//父类的原形方法
Parent.prototype.alertFlag = function () {
    alert(this.flag);
};
//子类
function Child() {
    this.flag = false;//修改属性(不写则不修改)
}
//Child 继承 Parent
Child.prototype = new Parent();
//添加原形方法
Child.prototype.sayHello = function () {
    alert("Hello");
};

var child = new Child();
child.alertFlag();//弹出 false
child.sayHello();// 弹出 Hello

//子类修改父类方法
Child.prototype.alertFlag = function () {
    alert(!this.flag);
};
child.alertFlag();//弹出 true

//总结:继承的方法为 Child.prototype = new Parent();(只有一句话)

借用构造函数继承

//借用构造函数继承
function Parent(name) {
    this.name = name;
}
function Child(name,age) {
    Parent.call(this,name);
    this.age = age;
}

//实例
var child = new Child("Andy",28);
alert(child.name);//Andy
alert(child.age);//28

//总结:继承的代码为Parent.call(this,name);(也是一句话),主要解决了this指向的转变和参数的传递。

组合继承

//组合继承
//父类
function Parent(name) {
    this.name = name;
    this.friends = ["Jay","Jolin"];
}
Parent.prototype.sayName = function () {
    alert(this.name);
};

//子类
function Child(name,age) {
    Parent.call(this,name);
    this.age = age;
}
//继承
Child.prototype = new Parent();
//改变constructor指向
Child.prototype.constructor = Child;

//子类添加方法
Child.prototype.sayAge = function () {
    alert(this.age);
};

//创建实例
var c1 = new Child("Andy",29);
var c2 = new Child("Lucy",24);

c1.friends.push("Jack");
c2.friends.push("Coco");

console.log(c1.friends.toString());//Jay,Jolin,Jack
console.log(c2.friends.toString());//Jay,Jolin,Coco

console.log(c1.sayName());//Andy
console.log(c2.sayName());//Lucy

原形式继承

//原形式继承
//实现继承的方法
function obj(o) {
    function F() {}
    F.prototype = o;
    return new F();
}

//但是ECMA5,通过Object.create()方法规范化了原形式继承(即上面的方法)

var person = {
    name:"Andy",
    age:29,
    friends:["Lily","Lucy","Jack"]
};

var Jay = Object.create(person);
Jay.name = "Jay";
Jay.friends.push("Jolin");

var Coco = Object.create(person);
Coco.name = "Coco";
Coco.friends.push("Sunny");

console.log(Jay.name);//Jay
console.log(Coco.name);//Coco
console.log(Jay.friends.toString());//Lily,Lucy,Jack,Jolin,Sunny
console.log(Coco.friends.toString());//Lily,Lucy,Jack,Jolin,Sunny

//没有重写的属性会被共享

var K = Object.create(person);
K.name = "Coco";
K.friends = ["J","Q","A"];

console.log(Jay.friends.toString());//Lily,Lucy,Jack,Jolin,Sunny
console.log(Coco.friends.toString());//Lily,Lucy,Jack,Jolin,Sunny
console.log(K.friends.toString());//J,Q,A

寄生式继承

//寄生式继承

//通过该方法,为子类添加方法,以实现继承;(即增强子类)
function create(child) {
    var clone = Object(child);
    clone.sayHi = function () {
        alert("Hi");
    };
    return clone;
}

var Me = {
    name : "Firefly",
    friends:["Bee","Cicada","Butterfly"]
};
var me = create(Me);

me.sayHi();

寄生组合继承(又称完美继承)

//寄生组合继承
function Parent(a) {
    this.a = a;
}
Parent.prototype = {
    fn:function () {
        alert("Hi");
    }
};
function Child(a,b) {
    Parent.call(this,a);
    this.b = b;
}
//实现继承的方法
function inheritPrototype(subType,superType) {
    var prototype = Object(superType.prototype);
    prototype.constructor = subType;
    subType.prototype = prototype;
}
//继承
inheritPrototype(Child,Parent);
//为Child添加原型方法
Child.prototype.sayB = function () {
    alert(this.b);
}

注:以下着重介绍组合寄生继承。

例:

function Super(name) {
    this.name = name;
}
Super.prototype = {
    constructor:Super,
    sayName:function () {
        alert(this.name);
    }
    //其他方法...
};
function Sub(name,age){
    Super.call(this,name);
    this.age = age;
}
//实现继承
inheritPrototype(Sub,Super);
//添加原形方法
Sub.prototype.sayAge = function () {
    alert(this.age);
};
//实现继承的方法
function inheritPrototype(subType,superType) {
    var prototype = Object(superType.prototype);
    prototype.constructor = subType;
    subType.prototype = prototype;
}

//创建实例
var s = new Sub("Andy",28);
//调用方法
s.sayName();
s.sayAge();
//修改属性
s.age = 24;
s.sayAge();
s.name = "Lily";
s.sayName();

实现多继承(修改inheritPrototype()方法)

//父类1
function Super1(name) {
    this.name = name;
}
Super1.prototype = {
    constructor:Super1,
    sayName:function () {
        alert(this.name);
    }
    //其他方法...
};
//父类2
function Super2(gender) {
    this.gender = gender;
}
Super2.prototype = {
    constructor:Super1,
    sayGender:function () {
        alert(this.gender);
    }
    //其他方法...
};
//子类
function Sub(name,gender,age){
    Super1.call(this,name);
    Super2.call(this,gender);
    this.age = age;
}
inheritPrototype(Sub,Super1);
inheritPrototype(Sub,Super2);
//添加原形方法
Sub.prototype.sayAge = function () {
    alert(this.age);
};
//实现继承的方法
function inheritPrototype(subType,superType) {
    var prototype = Object(superType.prototype);
    prototype.constructor = subType;
    //修改的地方
    //subType.prototype = prototype;
    for(par in prototype){
        subType.prototype[par] = prototype[par];
    }
}
//创建实例
var s = new Sub("Andy","man",26);
s.sayName();
s.sayGender();
s.sayAge();

另外,你可以将Super1、Super2和Sub类放在不同的js文件中,在html中引入后调用。

例如:

//将以下代码方法myjs1.js文件中
function Super1(name) {
    this.name = name;
}
Super1.prototype = {
    constructor:Super1,
    sayName:function () {
        alert(this.name);
    }
    //其他方法...
};

//将以下代码放入myjs2.js文件中
function Super2(gender) {
    this.gender = gender;
}
Super2.prototype = {
    constructor:Super1,
    sayGender:function () {
        alert(this.gender);
    }
    //其他方法...
};

//将以下代码放入myjs3.js文件中
function Sub(name,gender,age){
    Super1.call(this,name);
    Super2.call(this,gender);
    this.age = age;
}
inheritPrototype(Sub,Super1);
inheritPrototype(Sub,Super2);
//添加原形方法
Sub.prototype.sayAge = function () {
    alert(this.age);
};
function inheritPrototype(subType,superType) {
    var prototype = Object(superType.prototype);
    prototype.constructor = subType;
    //subType.prototype = prototype;
    for(par in prototype){
        subType.prototype[par] = prototype[par];
    }
}

//在html中引用
<script src="myjs1.js"></script>
<script src="myjs2.js"></script>
<script src="myjs3.js"></script>
<script>
    //创建实例
    var s = new Sub("Andy","man",26);
    s.sayName();
    s.sayGender();
    s.sayAge();
</script>

Demo:超级玛丽
超级玛丽,有两个属性:name和size,有三个方法:show()、run()和jump();
大的超级玛丽:继承自超级玛丽,在超级玛丽的三个方法基础上修改一个方法:jump();
医生超级玛丽:继承自大的超级玛丽,在大的超级玛丽的三个方法基础上多了一个方法:shot();

超级玛丽类(js1.js):

function SuperMarie(name,size) {
    this.name = name;
    this.size = size;
}
SuperMarie.prototype = {
    constructor:SuperMarie,
    jump:function () {
        console.log(this.name+" jump.");
    },
    run:function () {
        console.log(this.name+" run.");
    },
    show:function () {
        console.log(this.name+"'s size is "+this.size);
    }
};

大的超级玛丽类(js2.js):

function BigSuperMarie(name,size) {
    SuperMarie.call(this,name,size);
}
inheritPrototype(BigSuperMarie,SuperMarie);
BigSuperMarie.prototype.jump=function () {
        console.log(this.name+" super jump!");
    };
function inheritPrototype(subType,superType) {
    var prototype = Object(superType.prototype);
    prototype.constructor = subType;
    for(par in prototype){
        subType.prototype[par] = prototype[par];
    }
}

医生超级玛丽类(js3.js):

function DoctorSuperMarie(name,size) {
    BigSuperMarie.call(this,name,size);
}
inheritPrototype(DoctorSuperMarie,BigSuperMarie);
DoctorSuperMarie.prototype.shot = function () {
        console.log(this.name+" shot!");
    };
function inheritPrototype(subType,superType) {
    var prototype = Object(superType.prototype);
    prototype.constructor = subType;
    for(par in prototype){
        subType.prototype[par] = prototype[par];
    }
}

html代码:

<button id="SuperMarie">Super Marie</button>
<button id="BigSuperMarie">Big Super Marie</button>
<button id="DoctorSuperMarie">Doctor Super Marie</button>

<br>

<button id="sizeBtn">Size</button>
<button id="runBtn">Run</button>
<button id="jumpBtn">Jump</button>
<button id="shotBtn">Shot</button>

<script src="js1.js"></script>
<script src="js2.js"></script>
<script src="js3.js"></script>
<script>
    var sm = new SuperMarie("Super Marie","small");//超级玛丽实例
    var bigSm =new BigSuperMarie("BigSuperMarie","big");//大的超级玛丽实例
    var docSm = new DoctorSuperMarie("DoctorSuperMarie","big");//医生超级玛丽实例

    var smBtn = document.getElementById("SuperMarie");//按钮:超级玛丽变小
    var bigSmBtn = document.getElementById("BigSuperMarie");//按钮:超级玛丽变大
    var docSmBtn = document.getElementById("DoctorSuperMarie");//按钮:超级玛丽变成医生超级玛丽

    var sizeBtn = document.getElementById("sizeBtn");//按钮:显示超级玛丽的大小
    var jumpBtn = document.getElementById("jumpBtn");//按钮:超级玛丽跳跃
    var runBtn = document.getElementById("runBtn");//按钮:超级玛丽奔跑
    var shotBtn = document.getElementById("shotBtn");//按钮:超级玛丽射击

    var me = "SuperMarie";

    smBtn.addEventListener("click",function () {
        me = "SuperMarie";
        console.log("I am SuperMarie!");
    });
    bigSmBtn.addEventListener("click",function () {
        me = "BigSuperMarie";
        console.log("I am BigSuperMarie!");
    });
    docSmBtn.addEventListener("click",function () {
        me = "DoctorSuperMarie";
        console.log("I am DoctorSuperMarie!");
    });

    sizeBtn.addEventListener("click",function () {
        if(me==="SuperMarie"){
            sm.show();
        }else if(me==="BigSuperMarie"){
            bigSm.show();//方法继承自父类
        }else if(me==="DoctorSuperMarie"){
            docSm.show();//方法继承自父类
        }
    });

    jumpBtn.addEventListener("click",function () {
        if(me==="SuperMarie"){
            sm.jump();
        }else if(me==="BigSuperMarie"){
            bigSm.jump();//修改父类方法
        }else if(me==="DoctorSuperMarie"){
            docSm.jump();//方法继承自父类
        }
    });

    runBtn.addEventListener("click",function () {
        if(me==="SuperMarie"){
            sm.run();
        }else if(me==="BigSuperMarie"){
            bigSm.run();//方法继承自父类
        }else if(me==="DoctorSuperMarie"){
            docSm.run();//方法继承自父类
        }
    });

    shotBtn.addEventListener("click",function () {
        if(me==="SuperMarie"){
            console.log("I can't shot!");
        }else if(me==="BigSuperMarie"){
            console.log("I can't shot!");
        }else if(me==="DoctorSuperMarie"){
            docSm.shot();
        }
    })

</script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值