如何实现Javascript ECMA 5';s array.map()用于稀疏数组?

如何实现Javascript ECMA 5';s array.map()用于稀疏数组?,javascript,Javascript,它应该很容易实现array.map(),也就是说,它接受一个函数,这个函数将由3个参数调用:元素值、索引、数组 但是对于稀疏数组呢?显然,如果只有索引0、1、2和100000有一个元素,或者从索引3稀疏到99999,我们不希望从索引0迭代到100000。我可以考虑使用arr.slice(0)或arr.concat()克隆数组,然后输入替换的值,但是如果我们不使用slice或concat,还有其他方法吗 我使用slice()提出的解决方案是: Array.prototype.collect = A

它应该很容易实现
array.map()
,也就是说,它接受一个函数,这个函数将由3个参数调用:元素值、索引、数组

但是对于稀疏数组呢?显然,如果只有索引0、1、2和100000有一个元素,或者从索引3稀疏到99999,我们不希望从索引0迭代到100000。我可以考虑使用
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;
};

collect
用于尝试代码,因为在某些语言中,这是
map
的另一个名称)

您不需要使用
此.slice(0)
。您只需将
result
设置为一个数组,并将值分配给任何索引:

Array.prototype.collect = Array.prototype.collect || function(fn) { 
  var result = [];
  for(var i in this) {
    if (this.hasOwnProperty(i)) { 
      result[i] = fn(this[i]);
    }
  }
  return result;
}

这应该很容易,但也有一些特殊的地方

允许回调函数修改有问题的数组。它添加或删除的任何元素都不会被访问。因此,我们似乎应该使用类似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;
}

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

var result=[]应该足够了。。。为什么要克隆阵列?还要注意,在某些浏览器中,
length
可能是可枚举的。如果我们设置
result=[]
,然后设置
result[0]=1
,然后设置
result[10000]=2
,它们是否相同,那么它就是一个稀疏数组,就像原始数组一样?所有未设置的索引都将默认为
未定义的
,就像任何其他不存在的属性一样。您如何定义“稀疏数组”以及如何在您的案例中创建一个?如果您这样做,
var a=[];a[5]=42
,那么数组的长度当然是
6
,但实际上它在索引
5
处只有一个元素。您将看到,如果执行
console.dir(a)
,那么似乎如果我们在空数组中设置一些元素,并且它们不是连续的,那么该数组就是稀疏数组。我使用
console.log
console.dir
转储了
arr.map
arr.collect
结果,它们看起来是一样的,所以看起来你有答案了。我尝试的稀疏数组是
arr=[1,3,7,9,11]
那么这是否意味着
array.map
实际上可以满足您的需要?您为什么将
map
定义为一个简单的函数并使用
this
?一个简单函数的
this
表示全局范围……您可以在事后将其分配给对象或原型的属性。例如,
Array.prototype.map=map
变量a=[];a、 地图=地图
然后当您在
a
上调用它时,“this”将具有正确的值。我本来可以写
Array.prototype.map=函数映射…
,但我没有。啊哈,是的,我想知道你为什么要创建一个额外的函数,而不是仅仅分配给Array.prototype,因为它显然是在处理数组
Array.prototype.map=map
可以完成,但是为什么要创建一个额外的悬空
map
@動靜能量, 我没有什么特别的理由去创建一个全局函数,而不是仅仅分配给数组原型。然而,值得注意的是,ECMA声明“映射函数是有意泛型的;它不要求它的
this
值是数组对象。”如果稀疏数组是
[1,2,,,,,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,
,由于尾部稀疏性,如果要与原始数组相同,我认为结果数组的长度属性应该与映射对象的长度属性相同(或多或少)。