如何在Javascript中实现类似数组的索引器([ ])?

3
我可以帮您翻译成中文。这段内容是关于JavaScript集合实现的问题,是否有办法为集合中的元素实现类似于数组的索引器?
目前,我有以下代码:
var Collection = function() {

    var collection = [];

    var addAccessor = function(api, name) {
      if (toString.call(collection[name]) == '[object Function]') {
        api[name] = (function(){
          return function () {
            return collection[name](arguments);
          };
        }());
      }
      else {
        Object.defineProperty(api, name, {
          get: function() { return collection.length; },
          enumerable: true,
          configurable: true
        });
      }
    };

    var publicApi = {};

    var methods = Object.getOwnPropertyNames(Array.prototype);
    for(var i = 0, len = methods.length; i < len; ++i) {
      var method = methods[i];
      addAccessor(publicApi, method);
    }

    return publicApi;
  };
};

所有Array.prototype的方法和属性都按预期工作。

var c = Collection();
c.push(4);
console.log(c.length);  // 1

但是我无法弄清楚如何使以下内容正常工作:
console.log(c[0]);     // should print 4, currently undefined

有没有什么方法可以做到这一点?

1
你不能这样做。你为什么不直接使用“数组”? - jbabey
我认为你的代码有些缺失。collection从未被填充,因此没有复制任何数组原型。你能发布一个可工作的fiddle吗? - David Hellsing
2个回答

3

如果你想要“扩展”Array,经典的方法可能是这样的:

function Collection(){};
Collection.prototype = new Array();
Collection.constructor = Collection;

现在添加自己的方法:

Collection.prototype.color = function() {
    this.push('color');
};

并使用new进行操作:

var myArray = new Collection();
myArray.push(1);
myArray.color();

如果你想添加一个访问数组 push 的新的 push 方法,请尝试以下操作:
Collection.prototype.push = function() {
    console.log('pushed!');
    Array.prototype.push.apply(this, [].slice.call(arguments));
};

这是我的起点,但我需要在一些数组方法上引发事件。在这种情况下,我该如何覆盖Collection.prototype.push,以便在将元素推入数组的同时执行自己的代码? - Bill
Array.prototype.push.apply(this, [].slice.call(arguments)); 导致堆栈溢出。 - Bill
错过了原型声明的更改,这就是我第一次尝试以这种方式实现它时所错过的,这让我陷入了一场徒劳的追逐... 这个方法完美地运行了。谢谢! - Bill
使用 Collection.prototype = Array.prototype 而不是 ... = new Array() 会更好吧?这样也可以包括数组原型本身的任何未来添加。 - ygoe
1
我发现了区别:我的建议是连接两个原型,修改Collection.prototype也会影响基本的Array.prototype。使用new Array()可以避免这种情况,应该优先考虑。未来对于Array.prototype的添加(在这种情况下)无论如何都会在新的Collection实例中可用。 - ygoe

0
使用类:
class Collection extends Array {
  color() {
    this.push('color')
  }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接