JavaScript 繼承

寄生組合繼承稱爲完美繼承(其餘繼承方式都有缺陷)html

如下爲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種繼承的詳細寫法。this

原形鏈繼承prototype

//原形鏈繼承
//父類
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();(只有一句話)

借用構造函數繼承code

//借用構造函數繼承
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指向的轉變和參數的傳遞。

組合繼承htm

//組合繼承
//父類
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

寄生式繼承ip

//寄生式繼承

//經過該方法,爲子類添加方法,以實現繼承;(即加強子類)
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();

寄生組合繼承(又稱完美繼承)get

//寄生組合繼承
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();

另外,你能夠將Super一、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>
相關文章
相關標籤/搜索