首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

JavaScript 原型鏈深度解析:__proto__、prototype、constructor 關係圖譜

     編輯:程式設計綜合問答

代碼:

function Box() {}
Box.prototype.name = 'Programmer';
Box.prototype.method = function() { return this.name; };
var box = new Box();

六個核心問題,一次講透。

核心結論速查表

問題答案
1. box.__proto__ 訪問什麼?Box.prototype 對象本身
2. box.method() vs box.__proto__.method() 差異?前者讀取原型方法,賦值會在實例創建遮蔽屬性;後者直接操作原型對象,影響所有實例
3. Box.prototype 是構造函數的原型對象嗎?是
4. 原型對象存儲在哪?堆內存,Box.prototype 指向它,所有實例 __proto__ 指向它
5. 實例原型的 __proto__ 指向哪?Object.prototype → null (原型鏈終點)
6. 構造函數 Box 的 __proto__ 指向哪?Function.prototype → Object.prototype → null

詳細圖解:原型鏈完整結構


┌─────────────────────────────────────────────────────────────┐
│                     Function.prototype                       │
│  (apply, call, bind, length, name, prototype: Object.prototype)│
└──────────────────────────┬──────────────────────────────────┘
                           │ [[Prototype]] (__proto__)
                           ▼
┌─────────────────────────────────────────────────────────────┐
│                         Box (函數對象)                        │
│  name: "Box"  length: 0  prototype: ──────────────────────┐  │
└─────────────────────────────────────────────────────────────┘  │
                                                                 │
                                                                 │ .prototype (顯式原型)
                                                                 ▼
┌─────────────────────────────────────────────────────────────┐
│                      Box.prototype (原型對象)                 │
│  constructor: Box  name: "Programmer"  method: ƒ()           │
│  __proto__: ──────────────────────────────────────────────┐  │
└─────────────────────────────────────────────────────────────┘  │
                                                                 │
                                                                 │ [[Prototype]] (__proto__)
                                                                 ▼
┌─────────────────────────────────────────────────────────────┐
│                      Object.prototype (根原型)                │
│  constructor: Object  toString: ƒ()  hasOwnProperty: ƒ() ...  │
│  __proto__: null (原型鏈終點)                                 │
└─────────────────────────────────────────────────────────────┘
                                                                 │
                              new Box()                          │
                                                                 ▼
┌─────────────────────────────────────────────────────────────┐
│                         box (實例對象)                        │
│  __proto__: ──────────────────────────────────────────────┐  │
└─────────────────────────────────────────────────────────────┘  │
                                                                 │
                                                                 │ [[Prototype]] (__proto__)
                                                                 ▼
                              (指向 Box.prototype)

關鍵驗證代碼

// 1. 核心關係
console.log(box.__proto__ === Box.prototype); // true
console.log(Box.prototype.__proto__ === Object.prototype); // true
console.log(Box.__proto__ === Function.prototype); // true
console.log(Object.prototype.__proto__ === null); // true

// 2. 遮蔽效應演示
box.method = 12;                    // 實例新增自身屬性
console.log(box.method);            // 12 (實例屬性)
console.log(box.__proto__.method);  // ƒ() (原型方法未變)
console.log(Box.prototype.method);  // ƒ()

Box.prototype.method = 1212;        // 修改原型
console.log(box.method);            // 12 (實例自身屬性遮蔽)
console.log(box.__proto__.method);  // 1212
console.log(Box.prototype.method);  // 1212

// 3. 新實例受原型修改影響
var box2 = new Box();
console.log(box2.method);           // 1212 (讀取原型)

// 4. hasOwnProperty 區分自身/繼承屬性
console.log(box.hasOwnProperty('method'));  // true (box 自己的)
console.log(box2.hasOwnProperty('method')); // false (繼承的)

ES6 class 語法糖本質相同

class Box {
    constructor() {}
    method() { return this.name; }
}
static name = 'Programmer'; // 類靜態屬性 ≠ 原型屬性

// 編譯後本質:
// Box.prototype.method = function() { ... }
// Object.defineProperty(Box, 'name', { value: 'Programmer' })

避坑指南

  • 不要直接修改 __proto__:box.__proto__ = otherProto 破壞繼承鏈,性能極差,已棄用
  • 用 Object.create() 創建純原型對象:const proto = { method() {} }; const obj = Object.create(proto);
  • 構造函數返回對象會覆蓋 this:function Box() { return {a:1}; } new Box() → {a:1} (非 Box 實例)
  • 箭頭函數不能做構造函數:無 prototype,無 this 綁定

掌握這張圖,JS 繼承機制就徹底懂了。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved