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

JavaScript 面向對象實戰:不使用 Array 構造器實現 MyArray

     編輯:程式設計疑難解答

需求

在無 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 難以完美模擬 []
lengthObject.defineProperty getter只讀

進階:ES6 Proxy 完美模擬下標

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 面向對象核心模式之一。

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