function F() {
var list = []; // 私有成員(局部變量)
}
F.prototype.method = function() {
// 這裡想訪問 list
};
var list 是 F 執行上下文中的局部變量,屬於 F 的詞法作用域。F.prototype.method 定義在全局/模塊作用域,其[[Scope]] 不包含 F 的執行上下文。F 內部,故無法捕獲 list。若需在實例方法中訪問私有變量,必須將方法定義在構造函數內部,形成閉包:
function F() {
var list = []; // 私有
this.method = function() { // 特權方法
// 可訪問 list
list.push(1);
return list;
};
}
缺點:每個實例都會創建獨立的 method 函數副本,佔用更多內存,無法共享。
function F() {
this._list = []; // 約定私有,實際可訪問
}
F.prototype.method = function() {
this._list.push(1); // 原型方法可訪問實例屬性
};
優點:原型共享、內存高效、語法簡單。缺點:非強制私有,依賴開發者自覺。
const LIST = Symbol('list');
class F {
constructor() { this[LIST] = []; }
method() { this[LIST].push(1); }
}
Symbol 屬性不可被 for...in、Object.keys 遍歷,較難被誤訪問。
class F {
#list = []; // 真正私有
method() { this.#list.push(1); }
}
語法層面強制私有,外部訪問直接報錯,推薦新項目使用。
const listMap = new WeakMap();
class F {
constructor() { listMap.set(this, []); }
method() { listMap.get(this).push(1); }
}
WeakMap 鍵為弱引用,不阻礙 GC,實現真私有且無內存洩漏風險。
#privateField(ES2022 標準)。_underscore 約定 + 代碼審查,或 WeakMap 方案。原型方法定義在構造函數外部,作用域鏈不包含構造函數的局部變量,故無法訪問私有成員。解決路徑:閉包(犧牲共享)、約定私有(_list)、Symbol、ES6 #私有字段、WeakMap。根據項目環境與團隊規範選擇。