国产成人精品久久免费动漫-国产成人精品天堂-国产成人精品区在线观看-国产成人精品日本-a级毛片无码免费真人-a级毛片毛片免费观看久潮喷

您的位置:首頁技術(shù)文章
文章詳情頁

JS繼承實現(xiàn)方法及優(yōu)缺點詳解

瀏覽:71日期:2024-04-22 13:27:47

前言

JS作為面向?qū)ο蟮娜躅愋驼Z言,繼承也是其非常強大的特性之一。那么如何在JS中實現(xiàn)繼承呢?讓我們拭目以待。

JS繼承的實現(xiàn)方式

既然要實現(xiàn)繼承,那么首先我們得有一個父類,代碼如下:

// 定義一個動物類function Animal (name) { // 屬性 this.name = name || ’Animal’; // 實例方法 this.sleep = function(){ console.log(this.name + ’正在睡覺!’); }}// 原型方法Animal.prototype.eat = function(food) { console.log(this.name + ’正在吃:’ + food);};

1、原型鏈繼承

核心: 將父類的實例作為子類的原型

function Cat(){ }Cat.prototype = new Animal();Cat.prototype.name = ’cat’;// Test Codevar cat = new Cat();console.log(cat.name);console.log(cat.eat(’fish’));console.log(cat.sleep());console.log(cat instanceof Animal); //true console.log(cat instanceof Cat); //true

特點:

非常純粹的繼承關(guān)系,實例是子類的實例,也是父類的實例 父類新增原型方法/原型屬性,子類都能訪問到 簡單,易于實現(xiàn)

缺點:

要想為子類新增屬性和方法,必須要在new Animal()這樣的語句之后執(zhí)行,不能放到構(gòu)造器中

無法實現(xiàn)多繼承

來自原型對象的所有屬性被所有實例共享(來自原型對象的引用屬性是所有實例共享的)(詳細(xì)請看附錄代碼: 示例1)創(chuàng)建子類實例時,無法向父類構(gòu)造函數(shù)傳參

推薦指數(shù):★★(3、4兩大致命缺陷)

2017-8-17 10:21:43補充:感謝 MMHS 指出。缺點1中描述有誤:可以在Cat構(gòu)造函數(shù)中,為Cat實例增加實例屬性。如果要新增原型屬性和方法,則必須放在new Animal()這樣的語句之后執(zhí)行。

2018-9-10 00:03:45補充:感謝 IRVING_J 指出。缺點3中的描述不夠充分。更正為:來自原型對象的所有屬性被所有實例共享。

2、構(gòu)造繼承

核心:使用父類的構(gòu)造函數(shù)來增強子類實例,等于是復(fù)制父類的實例屬性給子類(沒用到原型)

function Cat(name){ Animal.call(this); this.name = name || ’Tom’;}// Test Codevar cat = new Cat();console.log(cat.name);console.log(cat.sleep());console.log(cat instanceof Animal); // falseconsole.log(cat instanceof Cat); // true

特點:

解決了1中,子類實例共享父類引用屬性的問題 創(chuàng)建子類實例時,可以向父類傳遞參數(shù) 可以實現(xiàn)多繼承(call多個父類對象)

缺點:

實例并不是父類的實例,只是子類的實例 只能繼承父類的實例屬性和方法,不能繼承原型屬性/方法 無法實現(xiàn)函數(shù)復(fù)用,每個子類都有父類實例函數(shù)的副本,影響性能

推薦指數(shù):★★(缺點3)

3、實例繼承

核心:為父類實例添加新特性,作為子類實例返回

function Cat(name){ var instance = new Animal(); instance.name = name || ’Tom’; return instance;}// Test Codevar cat = new Cat();console.log(cat.name);console.log(cat.sleep());console.log(cat instanceof Animal); // trueconsole.log(cat instanceof Cat); // false

特點:

不限制調(diào)用方式,不管是new 子類()還是子類(),返回的對象具有相同的效果

缺點:

實例是父類的實例,不是子類的實例 不支持多繼承

推薦指數(shù):★★

4、拷貝繼承

function Cat(name){ var animal = new Animal(); for(var p in animal){ Cat.prototype[p] = animal[p]; } Cat.prototype.name = name || ’Tom’;}// Test Codevar cat = new Cat();console.log(cat.name);console.log(cat.sleep());console.log(cat instanceof Animal); // falseconsole.log(cat instanceof Cat); // true

特點:

支持多繼承

缺點:

效率較低,內(nèi)存占用高(因為要拷貝父類的屬性) 無法獲取父類不可枚舉的方法(不可枚舉方法,不能使用for in 訪問到)

推薦指數(shù):★(缺點1)

5、組合繼承

核心:通過調(diào)用父類構(gòu)造,繼承父類的屬性并保留傳參的優(yōu)點,然后通過將父類實例作為子類原型,實現(xiàn)函數(shù)復(fù)用

function Cat(name){ Animal.call(this); this.name = name || ’Tom’;}Cat.prototype = new Animal();// 感謝 @學(xué)無止境c 的提醒,組合繼承也是需要修復(fù)構(gòu)造函數(shù)指向的。Cat.prototype.constructor = Cat;// Test Codevar cat = new Cat();console.log(cat.name);console.log(cat.sleep());console.log(cat instanceof Animal); // trueconsole.log(cat instanceof Cat); // true

特點:

彌補了方式2的缺陷,可以繼承實例屬性/方法,也可以繼承原型屬性/方法 既是子類的實例,也是父類的實例 不存在引用屬性共享問題 可傳參 函數(shù)可復(fù)用

缺點:

調(diào)用了兩次父類構(gòu)造函數(shù),生成了兩份實例(子類實例將子類原型上的那份屏蔽了)推薦指數(shù):★★★★(僅僅多消耗了一點內(nèi)存)

6、寄生組合繼承

核心:通過寄生方式,砍掉父類的實例屬性,這樣,在調(diào)用兩次父類的構(gòu)造的時候,就不會初始化兩次實例方法/屬性,避免的組合繼承的缺點

function Cat(name){ Animal.call(this); this.name = name || ’Tom’;}(function(){ // 創(chuàng)建一個沒有實例方法的類 var Super = function(){}; Super.prototype = Animal.prototype; //將實例作為子類的原型 Cat.prototype = new Super();})();// Test Codevar cat = new Cat();console.log(cat.name);console.log(cat.sleep());console.log(cat instanceof Animal); // trueconsole.log(cat instanceof Cat); //true感謝 @bluedrink 提醒,該實現(xiàn)沒有修復(fù)constructor。Cat.prototype.constructor = Cat; // 需要修復(fù)下構(gòu)造函數(shù)

感謝 @bluedrink 提醒,該實現(xiàn)沒有修復(fù)constructor。

Cat.prototype.constructor = Cat; // 需要修復(fù)下構(gòu)造函數(shù)

特點:

堪稱完美

缺點:

實現(xiàn)較為復(fù)雜

推薦指數(shù):★★★★(實現(xiàn)復(fù)雜,扣掉一顆星)

附錄代碼:

示例一:

function Animal (name) { // 屬性 this.name = name || ’Animal’; // 實例方法 this.sleep = function(){ console.log(this.name + ’正在睡覺!’); } //實例引用屬性 this.features = [];}function Cat(name){}Cat.prototype = new Animal();var tom = new Cat(’Tom’);var kissy = new Cat(’Kissy’);console.log(tom.name); // 'Animal'console.log(kissy.name); // 'Animal'console.log(tom.features); // []console.log(kissy.features); // []tom.name = ’Tom-New Name’;tom.features.push(’eat’);//針對父類實例值類型成員的更改,不影響console.log(tom.name); // 'Tom-New Name'console.log(kissy.name); // 'Animal'//針對父類實例引用類型成員的更改,會通過影響其他子類實例console.log(tom.features); // [’eat’]console.log(kissy.features); // [’eat’]

原因分析:

關(guān)鍵點:屬性查找過程

執(zhí)行tom.features.push,首先找tom對象的實例屬性(找不到),

那么去原型對象中找,也就是Animal的實例。發(fā)現(xiàn)有,那么就直接在這個對象的features屬性中插入值。

在console.log(kissy.features); 的時候。同上,kissy實例上沒有,那么去原型上找。

剛好原型上有,就直接返回,但是注意,這個原型對象中features屬性值已經(jīng)變化了。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持好吧啦網(wǎng)。

標(biāo)簽: JavaScript
相關(guān)文章:
主站蜘蛛池模板: 在线看片欧美 | 亚洲午夜网| 亚洲在线视频网站 | 久久99精品久久久久久秒播 | 成人精品一区二区激情 | 欧美精品a毛片免费观看 | 国产伦久视频免费观看视频 | 国内精品久久久久久久星辰影视 | 三级亚洲 | 国产精品免费一区二区区 | 免费日韩一级片 | 国产一级内谢a级高清毛片 国产一级片毛片 | 成人丁香乱小说 | 91香蕉国产在线观看免费永久 | 伊在人香蕉99久久 | 亚洲国产另类久久久精品小说 | 亚欧精品在线观看 | a级一片| 欧美精品在线视频观看 | 精品国产免费观看久久久 | 亚洲字幕| 久久久精品国产免费观看同学 | 成人午夜在线播放 | 九九99九九视频在线观看 | 91最新91精品91蝌蚪 | 久久国产热视频 | 91精品国产91热久久久久福利 | 久久欧洲视频 | 91成人在线播放 | 一区不卡在线观看 | 亚洲一区二区三区91 | 韩国自拍偷自拍亚洲精品 | 国产在线精品福利一区二区三区 | 成年女人免费视频播放成年m | 女人a级毛片| 国产三级在线播放线 | 国产男女 爽爽爽爽视频 | 成人欧美一区二区三区视频 | 日韩欧美精品一区二区 | 91亚洲精品久久91综合 | 国产精品国内免费一区二区三区 |