在無 Array 構造器/字面量的環境下,自定義 MyArray 滿足:
var a = new MyArray(1,2,3,"test");
a.toString(); // "1,2,3,test"
a[a.length-1]; // "test" (需支持下標訪問)
a.push("boo"); // 返回 5
a.pop(); // 返回 "[boo]"
利用構造函數閉包保存私有 list,暴露方法操作之。
var MyArray = function() {
var list = []; // 私有存儲
// 構造參數寫入
for (var i = 0; i < arguments.length; i++)
list.push(arguments[i]);
// toString
this.toString = function() {
return list.join(',');
};
// 下標訪問:模擬 a[index]
this.at = function(index) {
if (index < 0 || index >= list.length) return null;
return list[index];
};
// 為支持 a[0] 寫法,需 Proxy (ES6) 或定義屬性
// 此處提供 .at() 方法替代
// push
this.push = function(item) {
list.push(item);
return list.length;
};
// pop
this.pop = function() {
var item = list.pop();
return '[' + item + ']';
};
// length 只讀屬性
Object.defineProperty(this, 'length', {
get: function() { return list.length; }
});
};
var a = new MyArray(1,2,3,"test");
console.log(a.toString()); // "1,2,3,test"
console.log(a.at(a.length-1)); // "test"
console.log(a.push("boo")); // 5
console.log(a.pop()); // "[boo]"
| 需求 | 實現方式 | 備註 |
|---|---|---|
| 構造參數 | arguments 遍歷 | 不定參數 |
| 私有存儲 | 閉包 var list | 外部不可直接訪問 |
| 下標訪問 | Object.defineProperty + Proxy (ES6) | 純 ES5 難以完美模擬 [] |
| length | Object.defineProperty getter | 只讀 |
var MyArray = function() {
var list = [];
// ... push/pop/toString 同前 ...
return new Proxy({}, {
get: function(target, prop) {
if (prop === 'length') return list.length;
var idx = parseInt(prop);
if (!isNaN(idx)) return list[idx];
return target[prop]; // 方法調用
},
set: function(target, prop, value) {
var idx = parseInt(prop);
if (!isNaN(idx)) { list[idx] = value; return true; }
target[prop] = value; return true;
}
});
};
閉包 + Object.defineProperty 可實現 90% 數組行為;ES6 Proxy 才能完美攔截 [] 下標操作。理解閉包封裝私有數據是 JS 面向對象核心模式之一。