Array.prototype.reduce = function(callback /*, initialValue*/) {
'use strict';
var t = this, len = t.length, k = 0, value;
//IF initial value provided - go to the for loop
if (arguments.length == 2) {
value = arguments[1];
}
else {
while (k < len && !(k in t)) {
k++;
}
//IF no values then THROW a TYPEERROR
if (k >= len) {
throw new TypeError('Reduce of empty array with no initial value');
}
value = t[k++];
}
for (; k < len; k++) {
if (k in t) {
value = callback(value, t[k], k, t);
}
}
return value;
};
polyfill from MDN:
else
问题:
脚本的while
... t
部分是做什么的?它背后的逻辑是什么?我认为这与提供额外的初始值参数有关。但是for
这里是数组上下文而不是方法的参数上下文。它似乎与(k in t)
循环做同样的工作。
这里else {
while (k < len && !(k in t)) {
k++;
}
if (...) {
...
}
value = t[k++];
}
表达式的逻辑是什么?为什么要根据实际数组值检查迭代器值?
{{1}}
答案 0 :(得分:2)
第1部分找到有效,现有初始值(如果尚未提供)。在稀疏数组中,您不能只假设array[0]
已设置。
如果我们声明:
var sparse = [];
sparse[1] = "something";
sparse[4] = "else";
然后sparse[0]
不是真正的值,并且不会是in sparse
。
您需要找到实际设置的第一个值。第一个索引是in
数组。
所以,从k == 0
开始:
while (k < len && !(k in t)) {
k++;
}
我们查看数组直到找到一个“真实”的索引。在我们的示例中,这将是sparse[1]
。
如果我们找不到,则下一个if
会抛出错误。
否则,
value = t[k++];
我们有初始值,继续前进。
第2部分循环遍历数组的其余实际元素,为每个元素调用回调,并跳过“缺失”索引:
for (; k < len; k++) {
if (k in t) {
value = callback(value, t[k], k, t);
}
}
在我们的示例中,我们会跳过2
和3
,接下来我们会调用sparse[4]
的回调。
如果数组不稀疏(例如var arr = [1,2,3,4];
),这一切都正常,它就不会跳过任何内容。