es5實(shí)現(xiàn)繼承

new方法的缺陷在于每個實(shí)例的屬性都是獨(dú)立的箱叁,無法共享,像一些函數(shù)的屬性我們是希望共享的惕医,所以就有了prototype的出現(xiàn)

在設(shè)計(jì)繼承的時(shí)候我們希望達(dá)到的效果是實(shí)例屬性都是各種獨(dú)自擁有的耕漱,但是放在prototype上的屬性是需要共享的,在后面評判各種繼承方式的優(yōu)缺點(diǎn)也是會參考這兩點(diǎn)的

六種方式:

1抬伺、原型鏈繼承

// 原型鏈繼承 子類的原型指向父類的實(shí)例
// 由于原型鏈繼承共享屬性實(shí)例屬性的缺點(diǎn)螟够,屬于引用類型傳值,引用副本實(shí)例屬性的修改必然會引起其他副本實(shí)例屬性的修改妓笙,所以不常使用;
// 另一個缺點(diǎn)在于不能向父類構(gòu)造函數(shù)隨時(shí)傳遞參數(shù)能岩,很不靈活
function SuperType() {
    this.colors = ['red', 'blue', 'green'];
}

function SubType() {}
SubType.prototype = new SuperType();
let instance1 = new SubType();
instance1.colors.push('black');
console.log(instance1.colors);
let instance2 = new SubType();
console.log(instance2.colors);

2、借用構(gòu)造函數(shù)繼承

// 借用構(gòu)造函數(shù)繼承, 在執(zhí)行Child構(gòu)造函數(shù)的時(shí)候捧灰,子類的實(shí)例各自得到一份構(gòu)造函數(shù)的副本,屬于值傳遞毛俏,所以子類之間的屬性修改是互不相關(guān)的炭庙;
// 缺點(diǎn):單獨(dú)使用無法達(dá)到函數(shù)復(fù)用煌寇,因?yàn)槊恳粋€函數(shù)和屬性都需要在構(gòu)造函數(shù)中定義焕蹄,沒法復(fù)用阀溶,即沒有父類prototype上的函數(shù)腻脏,只有不能共用的實(shí)例屬性
// 而且instanceof操作無法確定子類實(shí)例和父類之間的關(guān)系鸦泳,因?yàn)樽宇惖膒rototype和父類無關(guān)
function Parent() {
    this.colors = ['red', 'blue', 'green'];
}

function Child() {
    Parent.call(this);
}

let instance3 = new Child();
instance3.colors.push('white');
console.log(instance3.colors);

let instance4 = new Child();
console.log(instance4.colors);

3永品、組合式繼承

把父類的一個實(shí)例設(shè)為子類的prototype,然后在子類的構(gòu)造函數(shù)內(nèi)調(diào)用父類的構(gòu)造函數(shù)鼎姐,調(diào)用這樣父類的實(shí)例屬性出現(xiàn)了兩個地方钾麸,調(diào)用父類構(gòu)造函數(shù)的時(shí)候?qū)崿F(xiàn)了子類實(shí)例對子類prototype上父類實(shí)例屬性的覆蓋炕桨,達(dá)到了較好的效果饭尝,既能傳參献宫,也可以實(shí)現(xiàn)是否共享的控制钥平,唯一的問題在于調(diào)用了兩次父類的構(gòu)造函數(shù)姊途,父類的實(shí)例屬性在子類prototype上浪費(fèi)了

// 組合繼承模式 常用 原型鏈繼承+構(gòu)造函數(shù)繼承
// 原型鏈繼承共享屬性(屬性方法和屬性)涉瘾, 構(gòu)造函數(shù)繼承父類構(gòu)造函數(shù)的實(shí)例屬性
// 缺點(diǎn): 調(diào)用了兩次父類構(gòu)造函數(shù)吭净,生成了兩份實(shí)例睡汹,一個子類實(shí)例寂殉,一個父類實(shí)例囚巴,父類實(shí)例作為prototype使用
function Person(name, age) {
    this.name = name;
    this.age = age;
    this.action = ['speak', 'run', 'eat'];
    console.log('我被調(diào)用了');
}
Person.prototype.say = function () {
    console.log(`my name is ${this.name} and I am ${this.age} years old!`);
};

function Student(name, age, score) {
    Person.call(this, name, age);  // 借用構(gòu)造函數(shù), 第一次調(diào)用父類構(gòu)造函數(shù)
    this.score = score;
}

Student.prototype = new Person();  // 原型鏈繼承, 第二次調(diào)用父類構(gòu)造函數(shù)
Student.prototype.constructor = Student;  // 將實(shí)例的原型上的構(gòu)造函數(shù)指定為當(dāng)前子類的構(gòu)造函數(shù)
Student.prototype.showScore = function () {
    console.log(`my score is ${this.score}`);
};

let xiaoming = new Student('xiaoming', 23, '88');
xiaoming.action.push('panio');
console.log(xiaoming.action);
xiaoming.say();
xiaoming.showScore();

let xiaohua = new Student('xiaohua', 24, '99');
console.log(xiaohua.action);
xiaohua.say();
xiaohua.showScore();

4友扰、原型式繼承

利用一個空對象作為中介,將某個對象直接賦值給空對象構(gòu)造函數(shù)的原型村怪。

function object(obj){
    function F(){}
    F.prototype = obj;
    return new F();
}

object()對傳入其中的對象執(zhí)行了一次淺復(fù)制秽浇,將構(gòu)造函數(shù)F的原型直接指向傳入的對象甚负。之所以要這樣創(chuàng)造一個空對象柬焕,就是為了看后續(xù)繼續(xù)添加屬性的過程不會污染原來的對象

var person = {
    name: "Nicholas",
    friends: ["Shelby", "Court", "Van"]
};

var anotherPerson = object(person);
anotherPerson.name = "Greg";
anotherPerson.friends.push("Rob");

var yetAnotherPerson = object(person);
yetAnotherPerson.name = "Linda";
yetAnotherPerson.friends.push("Barbie");

alert(person.friends);   //"Shelby,Court,Van,Rob,Barbie"

缺點(diǎn):

原型鏈繼承多個實(shí)例的引用類型屬性指向相同梭域,存在篡改的可能斑举。
無法傳遞參數(shù)

另外病涨,ES5中存在Object.create()的方法富玷,能夠代替上面的object方法,因?yàn)閛bject方法其本質(zhì)就是一個淺復(fù)制的過程赎懦。

個人認(rèn)為這種繼承方式很不好雀鹃,每次繼承都直接返回一個對象励两,要繼續(xù)在對象上面擴(kuò)展黎茎,麻煩当悔,下面這種寫法或許更好

    function extend(Child, Parent) {
    var F = function(){};
    F.prototype = Parent.prototype;
    Child.prototype = new F();
    Child.prototype.constructor = Child;
  }
    // extend函數(shù)做的就是創(chuàng)造一個空對象作為Child的prototype工三,該空對象的__proto__又指向Parent

5先鱼、寄生式繼承

核心:在原型式繼承的基礎(chǔ)上,增強(qiáng)對象焙畔,返回的也直接是一個對象,所以寄生式繼承就相當(dāng)于一個工廠函數(shù)串远,里面對被繼承的對象進(jìn)行加強(qiáng),丟進(jìn)去要繼承的對象澡罚,出來一個已經(jīng)加強(qiáng)過的新對象

function createAnother(original){
    var clone = object(original); // 通過調(diào)用 object() 函數(shù)創(chuàng)建一個新對象
    clone.sayHi = function(){  // 以某種方式來增強(qiáng)對象
        alert("hi");
    };
    return clone; // 返回這個對象
}

函數(shù)的主要作用是為構(gòu)造函數(shù)新增屬性和方法,以增強(qiáng)函數(shù)

var person = {
    name: "Nicholas",
    friends: ["Shelby", "Court", "Van"]
};
var anotherPerson = createAnother(person);
anotherPerson.sayHi(); //"hi"

缺點(diǎn)(同原型式繼承):

原型鏈繼承多個實(shí)例的引用類型屬性指向相同留搔,存在篡改的可能更胖。
無法傳遞參數(shù)

6隔显、寄生組合式繼承

// 最好的方法却妨,最理想的方法 寄生組合式繼承
// 解決了兩次調(diào)用父類構(gòu)造函數(shù)問題
function Person_1(name, age) {
    this.name = name;
    this.age = age;
    this.action = ['speak', 'run', 'eat'];
    console.log('我被調(diào)用了');
}
Person_1.prototype.say = function () {
    console.log(`my name is ${this.name} and I am ${this.age} years old!`);
};

function Student_1(name, age, score) {
    Person_1.call(this, name, age);  // 借用構(gòu)造函數(shù), 第一次調(diào)用父類構(gòu)造函數(shù)
    this.score = score;
}

Student_1.prototype = Object.create(Person_1.prototype);
Student_1.prototype.constructor  = Student_1;
Student_1.prototype.showScore = function () {
    console.log(`my score is ${this.score}`);
};

let xiaoming_1 = new Student('xiaoming_1', 23, '78');
xiaoming_1.action.push('panio');
console.log(xiaoming_1.action);
xiaoming_1.say();
xiaoming_1.showScore();

let xiaohua_1 = new Student('xiaohua_1', 24, '89');
console.log(xiaohua_1.action);
xiaohua_1.say();
xiaohua_1.showScore();
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末括眠,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子掷豺,更是在濱河造成了極大的恐慌,老刑警劉巖当船,帶你破解...
    沈念sama閱讀 211,561評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件题画,死亡現(xiàn)場離奇詭異生年,居然都是意外死亡婴程,警方通過查閱死者的電腦和手機(jī)抱婉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,218評論 3 385
  • 文/潘曉璐 我一進(jìn)店門档叔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人衙四,你說我怎么就攤上這事〈福” “怎么了押逼?”我有些...
    開封第一講書人閱讀 157,162評論 0 348
  • 文/不壞的土叔 我叫張陵谭贪,是天一觀的道長专控。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么灾搏? 我笑而不...
    開封第一講書人閱讀 56,470評論 1 283
  • 正文 為了忘掉前任挫望,我火速辦了婚禮,結(jié)果婚禮上狂窑,老公的妹妹穿的比我還像新娘媳板。我一直安慰自己泉哈,他們只是感情好蛉幸,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,550評論 6 385
  • 文/花漫 我一把揭開白布丛晦。 她就那樣靜靜地躺著巨缘,像睡著了一般采呐。 火紅的嫁衣襯著肌膚如雪若锁。 梳的紋絲不亂的頭發(fā)上斧吐,一...
    開封第一講書人閱讀 49,806評論 1 290
  • 那天又固,我揣著相機(jī)與錄音煤率,去河邊找鬼仰冠。 笑死蝶糯,一個胖子當(dāng)著我的面吹牛洋只,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播识虚,決...
    沈念sama閱讀 38,951評論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼肢扯,長吁一口氣:“原來是場噩夢啊……” “哼担锤!你這毒婦竟也來了蔚晨?” 一聲冷哼從身側(cè)響起肛循,我...
    開封第一講書人閱讀 37,712評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎多糠,沒想到半個月后累舷,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體夹孔,經(jīng)...
    沈念sama閱讀 44,166評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡笋粟,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,510評論 2 327
  • 正文 我和宋清朗相戀三年析蝴,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片闷畸。...
    茶點(diǎn)故事閱讀 38,643評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖佑菩,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情裁赠,我是刑警寧澤,帶...
    沈念sama閱讀 34,306評論 4 330
  • 正文 年R本政府宣布佩捞,位于F島的核電站,受9級特大地震影響一忱,放射性物質(zhì)發(fā)生泄漏莲蜘。R本人自食惡果不足惜帘营,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,930評論 3 313
  • 文/蒙蒙 一票渠、第九天 我趴在偏房一處隱蔽的房頂上張望芬迄。 院中可真熱鬧问顷,春花似錦、人聲如沸杜窄。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,745評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽哗戈。三九已至荷科,卻和暖如春唯咬,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背胆胰。 一陣腳步聲響...
    開封第一講書人閱讀 31,983評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留刻获,地道東北人。 一個月前我還...
    沈念sama閱讀 46,351評論 2 360
  • 正文 我出身青樓蝎毡,卻偏偏與公主長得像,于是被迫代替她去往敵國和親沐兵。 傳聞我的和親對象是個殘疾皇子别垮,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,509評論 2 348

推薦閱讀更多精彩內(nèi)容