面向對象的四種繼承方式
第一種繼承:使用call,apply方法,將父對象的構造函數綁定在子對象上
function Xs(){
this.type = "學生";
}
function Dxs(name,age,sex){
Xs.call(this,arguments); //最簡單的辦法:構造函數的綁定
//使用call或者apply方法,將父對象的構造函數綁定在子對象
this.name = name;
this.age = age;
this.sex = sex;
}
function Xxs(name,age,sex){
Xs.apply(this,arguments);
this.name = name;
this.age = age;
this.sex = sex;
}
var xm = new Dxs("小明",18,"男");
var xh = new Xxs("小花",8,"女");
console.log(xm); //Dxs{"小明",18,"男","學生"}
console.log(xh);//Xxs{"小花",8,"女","學生"}
第二種繼承:通過原型對象(ptototype),可以把屬性和方法綁定到我們的對象上
function Xs(){
this.type = "學生";
}
function Dxs(name,age,sex){
this.name = name;
this.age = age;
this.sex = sex;
}
Dxs.prototype = new Xs(); //把Xs的type屬性給了Dxs的原型對象上面
//這句話是將Dxs的prototype指向Xs,他會刪除Dxs.prototype原本的值,并賦予一個新的值(Xs的值)
Dxs.prototype.constructor = Dxs; //將Dxs的原型對象繼承Xs的實例后重新指向Dxs
var xm = new Dxs("小明",18,"男");
console.log(xm);
console.log(Dxs.prototype.constructor == Dxs)//Dxs.prototype = new Xs();存在時輸出false,不存在時 是true
console.log(Dxs.prototype.constructor == Xs) //true
第三種繼承:直接繼承(protorype寫在函數外面)
function Xs(){}//空函數
Xs.prototype.type = "學生";
function Dxs(name,age,sex){
this.name = name;
this.age = age;
this.sex = sex;
}
Dxs.prototype = Xs.prototype; //賦值,把Xs的原型對象賦值給了Dxs的原型對象;
//通過這句話,Dxs的原型對象繼承自了學生,綁定了Xs的本體,那么,他們兩個就綁定在了一起
Dxs.prototype.constructor = Dxs; //這句話,相當于同時把Dxs的原型對象和Xs的原型對象都指向Dxs
var xm = new Dxs("小明",18,"男");
console.log(xm);
console.log(Dxs.prototype.constructor == Xs.prototype.constructor) //true
//優點:效率比較高,不占用內存,第二個繼承,實例化了Xs,那么就要占用一個空間,這個方法沒有實例化Xs,就不用占用一個多余的空間
//缺點:Dxs.prototype和Xs的原型對象指向同一個對象了
第四種繼承:利用空對象作為中介
var F = function(){}; //創建空對象
function Xs(){}; //創建父對象
Xs.prototype.type = "學生";
F.prototype = Xs.prototype;//空對象的原型對象繼承父對象
function Dxs(name,age){ //子對象
this.name = name;
this.age = age;
}
Dxs.prototype = new F();//子對象繼承空對象
Dxs.prototype.constructor = Dxs;//指針重新指回自己
var xm = new Dxs("小明",18);
console.log(xm.type);
console.log(Xs.prototype.constructor == Dxs);
//第一步,創建一個空函數
//第二步,創建父對象
//第三步,空對象的原型對象繼承父對象
//第四,創建子對象
//第五步:子對象繼承空對象
//那么Dxs.prototype.constructor = Dxs就不會改變父對象的prototype
//空對象不占用內存,Dxs繼承的是空對象,所以不會改變父對象Xs的指向,至于空對象影不影響無所謂
繼承封裝
function extend(child,parent){
var c = child.prototype;
var p = parent.prototype;
for(var i in p){
c[i] = p[i];
}
}
function Xs(){};
Xs.prototype.type = "學生";
function Dxs(name,age){
this.name = name;
this.age = age;
}
extend(Dxs,Xs)
var xm = new Dxs("小明",18);
console.log(xm.type);
console.log(Xs.prototype.constructor == Xs);