"Reducing Filter and Map Down to Reduce" by Elijah Manor概述了Array.prototype.reduce()
的以下用例:
鉴于以下数据(来自链接文章):
var doctors = [
{ number: 1, actor: "William Hartnell", begin: 1963, end: 1966 },
{ number: 2, actor: "Patrick Troughton", begin: 1966, end: 1969 },
{ number: 3, actor: "Jon Pertwee", begin: 1970, end: 1974 },
{ number: 4, actor: "Tom Baker", begin: 1974, end: 1981 },
{ number: 5, actor: "Peter Davison", begin: 1982, end: 1984 },
{ number: 6, actor: "Colin Baker", begin: 1984, end: 1986 },
{ number: 7, actor: "Sylvester McCoy", begin: 1987, end: 1989 },
{ number: 8, actor: "Paul McGann", begin: 1996, end: 1996 },
{ number: 9, actor: "Christopher Eccleston", begin: 2005, end: 2005 },
{ number: 10, actor: "David Tennant", begin: 2005, end: 2010 },
{ number: 11, actor: "Matt Smith", begin: 2010, end: 2013 },
{ number: 12, actor: "Peter Capaldi", begin: 2013, end: 2013 }
];
我们可以使用.reduce()
同时修改和过滤数据,如下所示(也来自链接文章):
doctors = doctors.reduce(function(memo, doctor) {
if (doctor.begin > 2000) { // this serves as our `filter`
memo.push({ // this serves as our `map`
doctorNumber: "#" + doctor.number,
playedBy: doctor.actor,
yearsPlayed: doctor.end - doctor.begin + 1
});
}
return memo;
}, []);
但是,为什么人们更喜欢这个而不是简单的for
循环呢?我怀疑它超出了具有相似内容的简单迭代循环(尽管我无法测试自Jsperf is down以来的声明)。
除了语法首选项之外,是否有任何理由(性能或其他方面)在简单循环上使用.reduce()
实现?
答案 0 :(得分:1)
像map
或reduce
这样的数组操作的一个客观好处是样板代码的固有变量范围和减少。比较:
var result = 0;
for (var i = 0, length = arr.length; i < length; i++) {
result += arr[i];
}
// vs:
var result = arr.reduce(function (acc, val) { return acc + val; }, 0);
巨型循环声明与你在这里尝试做的事情没有任何关系,它只是样板代码。此外,您的范围现在有两个额外的变量i
和length
浮动,没有人要求,如果您不小心,可能会或可能不会引入一些非明显的错误。
另一方面,reduce
代码只包含执行所需操作所需的最少部分。在像CoffeeScript这样的东西中,它的语法甚至可以进一步简化为arr.reduce (acc, val) -> acc + val
,这非常简洁。即使你需要在循环/回调中的操作期间创建额外的变量,那些不会使外部范围混乱。
其次,reduce
是一个众所周知的范例,可以作为该代码块意图的良好声明。您不需要解析无用的辅助变量并弄清楚它们的用途,您可以简单地将操作分解为正在操作的数组(arr
)以及回调表达式的结果(acc + val
)将产生,然后在整个数组上推断出结果将是什么。
潜在的这样的操作,但我认为这在实践中大多没有看到。