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

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

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

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

前言

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

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

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

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

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

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

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

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

優(yōu)點:實現(xiàn)了方法的繼承,寫起來簡單。

缺點

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

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

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

為了解決引用共享和傳參問題,誕生了“借用構(gòu)造函數(shù)”的方式,在子類構(gòu)造函數(shù)里調(diào)用父類構(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)父類構(gòu)造函數(shù)
}

const dog1 = new Dog('旺財');
const dog2 = new Dog('來福');

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

優(yōu)點

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

缺點

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

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

三、組合繼承:取長補短

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

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

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

const dog1 = new Dog('旺財');
const dog2 = new Dog('來福');

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

優(yōu)點

  • 解決了引用共享問題。
  • 可以向父類傳參。
  • 繼承了父類原型上的方法。

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

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

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

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

const animal = {
  name: '動物',
  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()方法,就是干這個的。

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

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

缺點:引用類型屬性還是會被共享。

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

五、寄生式繼承:給繼承加個包裝

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

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

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

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

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

六、寄生組合繼承:最完美的姿勢

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

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

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

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

const dog1 = new Dog('旺財');
const dog2 = new Dog('來福');

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

優(yōu)點

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

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

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

ES6引入了class關(guān)鍵字,讓繼承寫起來像其他語言一樣優(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)用父類構(gòu)造函數(shù)
    this.breed = breed;
  }
  bark() {
    console.log('汪汪汪');
  }
}

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

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

優(yōu)點

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

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

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

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

九、實際開發(fā)中怎么選

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

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

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

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

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

JS的繼承演進史,其實就是一部從“手動擋”到“自動擋”的發(fā)展史:

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

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

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

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

相關(guān)文章

最新評論

枝江市| 五大连池市| 崇左市| 康定县| 靖远县| 施甸县| 东海县| 肃北| 广宁县| 成都市| 本溪市| 浏阳市| 汶川县| 雷州市| 临汾市| 南阳市| 浮山县| 贵港市| 启东市| 临邑县| 乌拉特中旗| 拉孜县| 宁乡县| 壤塘县| 日土县| 措勤县| 尼玛县| 大冶市| 承德市| 绥滨县| 高阳县| 上饶市| 乐昌市| 洞口县| 淄博市| 岱山县| 新乡县| 梁平县| 儋州市| 安平县| 衡阳市|