萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 程式設計 >  >> 網頁製作 >> 互動設計

前端必修課:JavaScript 原型與繼承機制深度解析(上)

原型與閉包是 JS 兩大難點。本文聚焦原型機制與基於原型的繼承,閉包將於下篇講解。若有疑問或糾錯,歡迎討論。

一、原型與構造函數

所有函數(含構造函數、普通函數)均有 prototype 屬性,指向原型對象。

function F() {}
alert(F.prototype instanceof Object); // true

構造函數實例化三步曲

function A(x) { this.x = x; }
var obj = new A(1);
  1. 創建對象:obj = new Object()
  2. 鏈接原型:obj.__proto__ = A.prototype,同時 obj.constructor === A.prototype.constructor(永恆指向構造函數的 prototype.constructor)
  3. 執行構造:A.call(obj, 1) 初始化實例屬性

三步完成後,obj 與 A 斷開聯繫。此時 obj 擁有實例屬性 x,並通過 __proto__ 訪問 A.prototype 成員。

驗證原型成員數量

var num = 0;
for (o in A.prototype) { alert(o); num++; }
alert("member: " + num);

原型共享機制

A.prototype.say = function() { alert("Hi"); };

所有 A 實例共享同一個 say 函數引用,而非各自複製副本。

二、原型鏈繼承實戰

簡易類式繼承(僅實例屬性)

function B(x, y) {
  this.tmpObj = A;
  this.tmpObj(x);  // 等價 A.call(this, x)
  delete this.tmpObj;
  this.y = y;
}

缺點:無法繼承 A.prototype 成員。

完美繼承:類式 + 原型鏈雙重繼承

function A(x) { this.x = x; }
A.prototype.a = "a";

function B(x, y) {
  this.y = y;
  A.call(this, x);  // 類式繼承實例屬性
}

B.prototype.b1 = function() { alert("b1"); };
B.prototype = new A();  // 原型鏈繼承:B.prototype → A 實例
B.prototype.b2 = function() { alert("b2"); };
B.prototype.constructor = B;  // 修正 constructor 指向

var obj = new B(1, 3);

關鍵點逐行解析

  1. B.prototype = new A():B 原型指向 A 實例 → 擁有 x(undefined)、a("a"),建立原型鏈
  2. 實例 obj 擁有兩個 x:實例屬性 x=1 遮蔽原型屬性 x=undefined
  3. b1 定義在 new A() 之前,被拋棄的原型對象帶走 → obj.b1 = undefined
  4. b2 定義在 之後,正常掛載於新原型
  5. B.prototype.constructor = B:修正構造器指向,否則 obj.constructor === A

原型鏈圖譜

obj → B.prototype (A 實例) → A.prototype → Object.prototype → null
     (x:1, y:3)     (x:undefined, a:"a", b2)  (a:"a")

核心心法: 先 A.call(this) 拿實例屬性,再 B.prototype = new A() 掛原型鏈,最後 在新原型上續增方法並修正 constructor。這就是 JS 原型繼承的標準範式。

copyright © 萬盛學電腦網 all rights reserved