最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JavaScript中繼承的七種方式對(duì)比總結(jié)

 更新時(shí)間:2026年03月24日 09:02:01   作者:kyriewen  
這篇文章小編就來(lái)和大家盤(pán)點(diǎn)一下JS里實(shí)現(xiàn)繼承的七種方式,從最基礎(chǔ)的到最完善的,讓你在面試官問(wèn)JS繼承有哪些方式時(shí),能從容應(yīng)對(duì),還能說(shuō)出各自的優(yōu)缺點(diǎn)

昨天我們聊了原型鏈,知道了JS對(duì)象之間是怎么“攀親戚”的。今天咱們來(lái)聊聊繼承——也就是怎么讓一個(gè)對(duì)象“認(rèn)祖歸宗”,繼承另一個(gè)對(duì)象的屬性和方法。從最原始的手動(dòng)操作,到ES6優(yōu)雅的class語(yǔ)法,這中間有好幾種姿勢(shì),每種都有自己的脾氣。今天一次性給你盤(pán)清楚。

前言

繼承在JS里就像“房產(chǎn)繼承”——你想把老爹的房子傳給孩子,但又不想直接把房子拆了重新蓋。不同的繼承方式,就像是不同的“過(guò)戶(hù)”手段,有的簡(jiǎn)單粗暴,有的精細(xì)巧妙,有的會(huì)留下后遺癥。

今天我們就來(lái)盤(pán)點(diǎn)JS里實(shí)現(xiàn)繼承的七種方式,從最基礎(chǔ)的到最完善的,讓你在面試官問(wèn)“JS繼承有哪些方式”時(shí),能從容應(yīng)對(duì),還能說(shuō)出各自的優(yōu)缺點(diǎn)。

一、原型鏈繼承:最原始的“血脈相連”

這是JS里最基礎(chǔ)的繼承方式,核心就是讓子類(lèi)的原型指向父類(lèi)的實(shí)例。

function Animal() {
  this.name = '動(dòng)物';
  this.colors = ['黑色', '白色'];
}
Animal.prototype.eat = function() {
  console.log('吃東西');
};

function Dog() {}
// 關(guān)鍵一步:讓Dog的原型指向Animal的實(shí)例
Dog.prototype = new Animal();

const dog1 = new Dog();
const dog2 = new Dog();

dog1.colors.push('金色');
console.log(dog2.colors); // ['黑色', '白色', '金色'] —— 哎呀,被改了!

優(yōu)點(diǎn):實(shí)現(xiàn)了方法的繼承,寫(xiě)起來(lái)簡(jiǎn)單。

缺點(diǎn)

  • 引用類(lèi)型的屬性會(huì)被所有實(shí)例共享,一個(gè)改了大家都改。
  • 無(wú)法向父類(lèi)構(gòu)造函數(shù)傳參。
  • 子類(lèi)實(shí)例的構(gòu)造函數(shù)被“篡改”成了Animal。

這種繼承就像家族企業(yè),祖宗留下的財(cái)產(chǎn)(比如房產(chǎn)證)大家共用,一個(gè)孫子把房子賣(mài)了,其他孫子都沒(méi)了。

二、構(gòu)造函數(shù)繼承:借雞生蛋

為了解決引用共享和傳參問(wèn)題,誕生了“借用構(gòu)造函數(shù)”的方式,在子類(lèi)構(gòu)造函數(shù)里調(diào)用父類(lèi)構(gòu)造函數(shù)。

function Animal(name) {
  this.name = name;
  this.colors = ['黑色', '白色'];
}
Animal.prototype.eat = function() {
  console.log('吃東西');
};

function Dog(name) {
  Animal.call(this, name); // 借調(diào)父類(lèi)構(gòu)造函數(shù)
}

const dog1 = new Dog('旺財(cái)');
const dog2 = new Dog('來(lái)福');

dog1.colors.push('金色');
console.log(dog1.colors); // ['黑色', '白色', '金色']
console.log(dog2.colors); // ['黑色', '白色'] —— 沒(méi)被影響!
console.log(dog1.eat); // undefined —— 父類(lèi)原型上的方法沒(méi)繼承到

優(yōu)點(diǎn)

  • 解決了引用共享問(wèn)題,每個(gè)實(shí)例有自己的屬性副本。
  • 可以向父類(lèi)傳遞參數(shù)。

缺點(diǎn)

  • 只能繼承父類(lèi)實(shí)例屬性,繼承不到父類(lèi)原型上的方法。
  • 方法都在構(gòu)造函數(shù)里定義,每次創(chuàng)建實(shí)例都會(huì)創(chuàng)建新方法,浪費(fèi)內(nèi)存。

這就像“借錢(qián)不借地”,你把老爹的現(xiàn)金拿來(lái)了,但老爹的祖宅(原型上的方法)沒(méi)拿到。

三、組合繼承:取長(zhǎng)補(bǔ)短

把原型鏈繼承和構(gòu)造函數(shù)繼承結(jié)合起來(lái),各取所長(zhǎng)。

function Animal(name) {
  this.name = name;
  this.colors = ['黑色', '白色'];
}
Animal.prototype.eat = function() {
  console.log('吃東西');
};

function Dog(name) {
  Animal.call(this, name); // 第二次調(diào)用父類(lèi)
}
Dog.prototype = new Animal(); // 第一次調(diào)用父類(lèi)
Dog.prototype.constructor = Dog; // 修正構(gòu)造函數(shù)指向

const dog1 = new Dog('旺財(cái)');
const dog2 = new Dog('來(lái)福');

dog1.colors.push('金色');
console.log(dog1.colors); // ['黑色', '白色', '金色']
console.log(dog2.colors); // ['黑色', '白色']
dog1.eat(); // 吃東西 —— 方法也繼承到了

優(yōu)點(diǎn)

  • 解決了引用共享問(wèn)題。
  • 可以向父類(lèi)傳參。
  • 繼承了父類(lèi)原型上的方法。

缺點(diǎn):父類(lèi)構(gòu)造函數(shù)被調(diào)用了兩次,造成了一定的性能浪費(fèi)和屬性冗余(實(shí)例上有,原型上也有)。

組合繼承是JS里最常用的繼承方式,雖然有小瑕疵,但足夠好用。ES6的class本質(zhì)上就是它的語(yǔ)法糖。

四、原型式繼承:Object.create的雛形

這種方式不涉及構(gòu)造函數(shù),直接通過(guò)一個(gè)對(duì)象創(chuàng)建另一個(gè)對(duì)象。

const animal = {
  name: '動(dòng)物',
  colors: ['黑色', '白色'],
  eat() {
    console.log('吃東西');
  }
};

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

const dog1 = createObject(animal);
const dog2 = createObject(animal);

dog1.colors.push('金色');
console.log(dog2.colors); // ['黑色', '白色', '金色'] —— 又被共享了

ES5提供了Object.create()方法,就是干這個(gè)的。

const dog1 = Object.create(animal);
const dog2 = Object.create(animal);

優(yōu)點(diǎn):不需要構(gòu)造函數(shù),直接基于已有對(duì)象創(chuàng)建新對(duì)象。

缺點(diǎn):引用類(lèi)型屬性還是會(huì)被共享。

這種繼承就像“克隆人”,克隆體共享同一個(gè)原型,一個(gè)改了大家都改。

五、寄生式繼承:給繼承加個(gè)包裝

在原型式繼承的基礎(chǔ)上,給新對(duì)象添加方法。

function createDog(original) {
  const clone = Object.create(original);
  clone.bark = function() {
    console.log('汪汪汪');
  };
  return clone;
}

const animal = { name: '動(dòng)物', eat() { console.log('吃東西'); } };
const dog = createDog(animal);
dog.bark(); // 汪汪汪

優(yōu)點(diǎn):可以在不修改原始對(duì)象的情況下添加新功能。

缺點(diǎn):和原型式繼承一樣,引用共享問(wèn)題依然存在;而且方法每次創(chuàng)建都會(huì)重新生成,沒(méi)法復(fù)用。

六、寄生組合繼承:最完美的姿勢(shì)

組合繼承的缺點(diǎn)是調(diào)用了兩次父類(lèi)構(gòu)造函數(shù)。寄生組合繼承解決了這個(gè)問(wèn)題,它被認(rèn)為是JS繼承的“最佳實(shí)踐”。

function Animal(name) {
  this.name = name;
  this.colors = ['黑色', '白色'];
}
Animal.prototype.eat = function() {
  console.log('吃東西');
};

function Dog(name) {
  Animal.call(this, name); // 只調(diào)用一次父類(lèi)
}

// 核心:用Object.create代替new Animal()
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
Dog.prototype.bark = function() {
  console.log('汪汪汪');
};

const dog1 = new Dog('旺財(cái)');
const dog2 = new Dog('來(lái)福');

dog1.colors.push('金色');
console.log(dog2.colors); // ['黑色', '白色'] —— 不受影響
dog1.eat(); // 吃東西
dog1.bark(); // 汪汪汪

優(yōu)點(diǎn)

  • 父類(lèi)構(gòu)造函數(shù)只調(diào)用一次。
  • 原型鏈干干凈凈,沒(méi)有冗余屬性。
  • 既有自己的屬性副本,又繼承了原型方法。

寄生組合繼承是目前最理想的繼承實(shí)現(xiàn)方式,也是ES6 class 背后做的事情。

七、ES6 Class:語(yǔ)法糖的終極形態(tài)

ES6引入了class關(guān)鍵字,讓繼承寫(xiě)起來(lái)像其他語(yǔ)言一樣優(yōu)雅。

class Animal {
  constructor(name) {
    this.name = name;
    this.colors = ['黑色', '白色'];
  }
  eat() {
    console.log('吃東西');
  }
}

class Dog extends Animal {
  constructor(name, breed) {
    super(name); // 調(diào)用父類(lèi)構(gòu)造函數(shù)
    this.breed = breed;
  }
  bark() {
    console.log('汪汪汪');
  }
}

const dog1 = new Dog('旺財(cái)', '土狗');
const dog2 = new Dog('來(lái)福', '金毛');

dog1.colors.push('金色');
console.log(dog2.colors); // ['黑色', '白色'] —— 完美
dog1.eat(); // 吃東西
dog1.bark(); // 汪汪汪

優(yōu)點(diǎn)

  • 語(yǔ)法清晰,易讀易寫(xiě)。
  • 底層就是寄生組合繼承,性能好。
  • 支持super關(guān)鍵字方便調(diào)用父類(lèi)方法。

缺點(diǎn):本質(zhì)還是原型那一套,但語(yǔ)法糖已經(jīng)夠甜了。

八、各種繼承方式對(duì)比總結(jié)

繼承方式優(yōu)點(diǎn)缺點(diǎn)適用場(chǎng)景
原型鏈繼承簡(jiǎn)單引用共享、不能傳參基本不用
構(gòu)造函數(shù)繼承解決引用共享、能傳參不能繼承原型方法基本不用
組合繼承兩者優(yōu)點(diǎn)都有調(diào)用兩次父類(lèi)以前常用
原型式繼承基于已有對(duì)象創(chuàng)建引用共享簡(jiǎn)單對(duì)象復(fù)用
寄生式繼承可添加新功能引用共享臨時(shí)增強(qiáng)對(duì)象
寄生組合繼承完美寫(xiě)法稍復(fù)雜ES6之前的首選
ES6 class語(yǔ)法優(yōu)雅、標(biāo)準(zhǔn)需要轉(zhuǎn)譯(老環(huán)境)現(xiàn)代開(kāi)發(fā)首選

九、實(shí)際開(kāi)發(fā)中怎么選

無(wú)腦選ES6 class。除非你還要兼容IE這種古董,否則直接用classextends就完事了。不僅代碼量少,而且不容易踩坑。

如果你好奇class底層干了啥,或者要寫(xiě)一些高階的繼承場(chǎng)景(比如混入multiple inheritance),那寄生組合繼承的手寫(xiě)實(shí)現(xiàn)還是值得掌握的。

function inherit(child, parent) {
  child.prototype = Object.create(parent.prototype);
  child.prototype.constructor = child;
}

這個(gè)工具函數(shù),就是寄生組合繼承的核心。

十、總結(jié):從“手動(dòng)擋”到“自動(dòng)擋”

JS的繼承演進(jìn)史,其實(shí)就是一部從“手動(dòng)擋”到“自動(dòng)擋”的發(fā)展史:

  • 原型鏈繼承是手動(dòng)擋,操作復(fù)雜容易出事。
  • 組合繼承是自動(dòng)擋,但油耗(性能)稍高。
  • 寄生組合繼承是CVT,平順又高效。
  • ES6 class是智能駕駛,你只管踩油門(mén),剩下的交給它。

無(wú)論哪種方式,底層都是原型鏈那一套。掌握了原型,繼承的七種姿勢(shì)不過(guò)是排列組合。以后面試官再問(wèn)“JS繼承有哪些方式”,你可以從容地把這七種娓娓道來(lái),順便告訴他:“但實(shí)際開(kāi)發(fā),我選ES6 class。”

明天我們將進(jìn)入JavaScript的另一個(gè)核心領(lǐng)域——異步編程,從回調(diào)地獄到Promise,再到async/await,帶你徹底理清JS的異步世界。

以上就是JavaScript中繼承的七種方式對(duì)比總結(jié)的詳細(xì)內(nèi)容,更多關(guān)于JavaScript繼承的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論

逊克县| 莫力| 曲周县| 陕西省| 曲麻莱县| 兰坪| 古交市| 毕节市| 莱西市| 汝州市| 长兴县| 丽江市| 扬州市| 云阳县| 双鸭山市| 肃北| 阿尔山市| 嘉义市| 平阴县| 乐亭县| 鲁山县| 抚州市| 措美县| 启东市| 中江县| 泽普县| 德惠市| 河源市| 弥渡县| 灯塔市| 南安市| 淮滨县| 文昌市| 巴中市| 西安市| 凤凰县| 洞口县| 石渠县| 阜阳市| 边坝县| 杂多县|