如何为稀疏数组实现Javascript ECMA 5的array.map()?

nop*_*ole 6 javascript

它应该很容易实现array.map(),它在ECMA-262中定义,它接受一个函数,这个函数将由3个参数调用:元素值,索引,数组.

但是对于稀疏数组呢?显然,如果只有索引0,1,2和100,000具有一个元素,并且从索引3到99,999稀疏,我们不希望从索引0迭代到100,000.我可以考虑使用arr.slice(0)arr.concat()克隆数组,然后输入替换值,但是如果我们不使用slice或者concat,还有其他方法吗?

我想出的解决方案slice()是:

Array.prototype.collect = Array.prototype.collect || function(fn) {
    var result = this.slice(0);

    for (var i in this) {
      if (this.hasOwnProperty(i))
        result[i] = fn(this[i], i, this);  // 3 arguments according to ECMA specs
    }
    return result;
};
Run Code Online (Sandbox Code Playgroud)

(collect用于试用代码,因为这是map某种语言的另一个名称)

Sam*_*ard 3

这应该很容易,但有一些特殊之处。

回调函数可以修改相关数组。它添加或删除的任何元素都不会被访问。所以看来我们应该使用类似 Object.keys 的东西来确定要访问哪些元素。

此外,结果被定义为一个新数组,就像由数组构造函数“创建”并获取旧数组的长度一样,因此我们也可以使用该构造函数来创建它。

这是考虑到这些因素的实现,但可能遗漏了一些其他微妙之处:

function map(callbackfn, thisArg) {
  var keys = Object.keys(this),
    result = new Array(this.length);

  keys.forEach(function(key) {
    if (key >= 0 && this.hasOwnProperty(key)) {
      result[key] = callbackfn.call(thisArg, this[key], key, this);
    }
  }, this);

  return result;
}
Run Code Online (Sandbox Code Playgroud)

我假设 Object.keys 按数字顺序返回数组的键,我认为这是实现定义的。如果没有,您可以对它们进行排序。