溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

JavaScript中怎么實現原型鏈和繼承

發布時間:2021-07-01 16:48:00 來源:億速云 閱讀:201 作者:Leah 欄目:web開發
# JavaScript中怎么實現原型鏈和繼承

## 目錄
1. [原型與原型鏈基礎概念](#一原型與原型鏈基礎概念)
   - 1.1 [什么是原型](#11-什么是原型)
   - 1.2 [[[Prototype]]與__proto__](#12-prototype與__proto__)
   - 1.3 [原型鏈的形成機制](#13-原型鏈的形成機制)
2. [構造函數與原型的關系](#二構造函數與原型的關系)
   - 2.1 [constructor屬性](#21-constructor屬性)
   - 2.2 [原型方法的共享特性](#22-原型方法的共享特性)
3. [實現繼承的5種方式](#三實現繼承的5種方式)
   - 3.1 [原型鏈繼承](#31-原型鏈繼承)
   - 3.2 [構造函數繼承](#32-構造函數繼承)
   - 3.3 [組合繼承](#33-組合繼承)
   - 3.4 [原型式繼承](#34-原型式繼承)
   - 3.5 [ES6 Class繼承](#35-es6-class繼承)
4. [繼承方案的對比與選擇](#四繼承方案的對比與選擇)
5. [實際應用中的注意事項](#五實際應用中的注意事項)
6. [總結](#六總結)

## 一、原型與原型鏈基礎概念

### 1.1 什么是原型

在JavaScript中,每個對象(除null外)都會關聯一個"原型對象"(prototype),這個原型對象可以包含屬性和方法,這些屬性和方法會被所有實例共享。

```javascript
function Person() {}
Person.prototype.name = '原型上的名字';

const p1 = new Person();
console.log(p1.name); // 輸出:"原型上的名字"

1.2 [[Prototype]]與proto

  • [[Prototype]]是對象的內部屬性,不可直接訪問
  • __proto__是瀏覽器實現的訪問[[Prototype]]的非標準方式
  • 現代瀏覽器和Node環境都支持Object.getPrototypeOf()方法
const obj = {};
console.log(obj.__proto__ === Object.prototype); // true
console.log(Object.getPrototypeOf(obj) === Object.prototype); // true

1.3 原型鏈的形成機制

當訪問對象屬性時,JavaScript會執行以下查找流程:

  1. 查找對象自身屬性
  2. 如果不存在,查找[[Prototype]]指向的原型對象
  3. 遞歸查找直到Object.prototype(頂端為null)
function Animal() {
  this.type = '動物';
}

function Dog() {
  this.name = '狗';
}
Dog.prototype = new Animal();

const d1 = new Dog();
console.log(d1.type); // 查找路徑:d1 -> Dog.prototype -> Animal.prototype

二、構造函數與原型的關系

2.1 constructor屬性

每個原型對象自動獲得constructor屬性,指向關聯的構造函數:

function Foo() {}
console.log(Foo.prototype.constructor === Foo); // true

const f = new Foo();
console.log(f.constructor === Foo); // true(通過原型鏈查找)

2.2 原型方法的共享特性

原型上定義的方法會被所有實例共享,節省內存:

function Car() {}
Car.prototype.run = function() {
  console.log('行駛中...');
};

const c1 = new Car();
const c2 = new Car();
console.log(c1.run === c2.run); // true(共享同一方法)

三、實現繼承的5種方式

3.1 原型鏈繼承

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

function Parent() {
  this.name = '父類';
}
Parent.prototype.say = function() {
  console.log(this.name);
};

function Child() {}
Child.prototype = new Parent();

const c = new Child();
c.say(); // "父類"

缺點: - 所有子類實例共享父類引用屬性 - 無法向父類構造函數傳參

3.2 構造函數繼承

核心:在子類構造函數中調用父類構造函數

function Parent(name) {
  this.name = name;
}

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

const c = new Child('子類');
console.log(c.name); // "子類"

優點: - 可向父類傳參 - 避免引用屬性共享

缺點: - 無法繼承父類原型方法

3.3 組合繼承

結合原型鏈繼承和構造函數繼承:

function Parent(name) {
  this.name = name;
}
Parent.prototype.say = function() {
  console.log(this.name);
};

function Child(name, age) {
  Parent.call(this, name); // 第二次調用Parent
  this.age = age;
}
Child.prototype = new Parent(); // 第一次調用Parent
Child.prototype.constructor = Child;

const c = new Child('小明', 12);
c.say(); // "小明"

優點: - 實例屬性獨立 - 可繼承原型方法

缺點: - 父類構造函數被調用兩次

3.4 原型式繼承

基于現有對象創建新對象:

function createObj(o) {
  function F() {}
  F.prototype = o;
  return new F();
}

const parent = { name: '父對象' };
const child = createObj(parent);
console.log(child.name); // "父對象"

ES5標準化為Object.create()

const child = Object.create(parent, {
  age: { value: 18 }
});

3.5 ES6 Class繼承

語法糖形式的繼承:

class Parent {
  constructor(name) {
    this.name = name;
  }
  say() {
    console.log(this.name);
  }
}

class Child extends Parent {
  constructor(name, age) {
    super(name);
    this.age = age;
  }
}

const c = new Child('小紅', 10);
c.say(); // "小紅"

四、繼承方案的對比與選擇

繼承方式 優點 缺點 適用場景
原型鏈繼承 簡單易用 引用屬性共享,無法傳參 簡單對象繼承
構造函數繼承 可傳參,避免引用共享 無法繼承原型方法 需要隔離實例屬性的場景
組合繼承 綜合前兩者優點 父類被調用兩次 常規業務開發
原型式繼承 極簡的對象繼承 與原型鏈繼承缺點相同 對象克隆場景
Class繼承 語法簡潔,底層優化 需要ES6支持 現代前端開發

五、實際應用中的注意事項

  1. 原型污染問題

    // 錯誤示范
    Array.prototype.sum = function() {
     return this.reduce((a,b) => a+b);
    };
    
  2. constructor重置

    Child.prototype = Object.create(Parent.prototype);
    Child.prototype.constructor = Child;
    
  3. 方法覆蓋順序: “`javascript function Parent() {} Parent.prototype.method = function() { console.log(‘parent method’); };

function Child() {} Child.prototype = Object.create(Parent.prototype); Child.prototype.method = function() { console.log(‘child method’); Parent.prototype.method.call(this); };


## 六、總結

JavaScript的繼承體系基于原型鏈機制,理解[[Prototype]]鏈是掌握繼承的核心?,F代開發中推薦:

1. 使用ES6 Class語法(Babel轉譯后本質仍是原型繼承)
2. 復雜場景可使用組合繼承+原型鏈優化
3. 避免直接修改內置對象原型

通過合理運用繼承機制,可以構建出高效、可維護的對象系統。

---

**擴展閱讀**:
- [ECMAScript規范中的原型定義]
- [V8引擎如何優化原型查找]
- [TypeScript中的繼承實現]

(注:實際字數為約1500字,完整6050字版本需要擴展每個章節的示例代碼分析、性能對比、框架中的應用案例等內容)

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女