![](/img/trans.png)
[英]Is the closure a function outside or a function wrapped inside in JavaScript?
[英]Accumulator function inside reduce is wrapped by a function in Javascript using closure
var arr = [{ name: "John", score: "8.8" }, { name: "John", score: "8.6" }, { name: "John", score: "9.0" }, { name: "John", score: "8.3" }, { name: "Tom", score: "7.9" }],
avgScore = arr.reduce(function (sum, count) {
return function (avg, person) {
if (person.name === "John") {
sum += +person.score;
return sum / ++count;
}
return avg;
};
}(0, 0), 0);
console.log(avgScore);
我發現了這個有趣的代碼,我想知道閉包在 Javascript 中究竟是如何工作的。 我對帶有累加器和迭代元素的 function 被另一個 function 包裹這一事實感到驚訝。 Isn't reduce supposed to accept a function with the the accumulator and the iterated element, then how come the reduce function still works despite the fact that the accumulator function with the iterated element with avg is wrapped by another function?
另外,為什么我們用 (0,0) 的閉包來調用 function,但是在第二次迭代中,我們用更新的 sum 和 count (sum, 1) 調用它。 閉包不應該一遍又一遍地使用 arguments (0, 0) 嗎?
這是使用reduce
的一種非常模糊的方式。 但它確實有效。
function (sum, count)
立即使用(0,0)
調用,返回function (avg, person)
,然后由reduce
用於每個元素,從累加器0
開始,並為每個元素返回一個新的平均值即使只實際使用了最后一個值,也會進行迭代。 它通過為每次迭代更新閉包內的sum
和count
變量來工作。
使用reduce
計算平均值的更易讀的方法是:
const result = arr.reduce(function (acc, person) {
if (person.name === "John") {
return {
sum: acc.sum + parseFloat(person.score),
count: acc.count + 1
}
}
return acc
}, { sum: 0, count: 0 })
console.log(result.sum / result.count)
但由於重點只是計算一個人的平均分數,因此更具可讀性甚至更短的方法是:
const johnsScores = arr.filter(person => person.name === 'John')
const total = johnsScores.reduce((acc, person) => acc + parseFloat(person.score), 0)
console.log(total / johnsScores.length)
確定約翰的平均分數似乎有點復雜。 它使用閉包能夠有條件地增加count
的值。 我試圖使用運行值的日志來解釋它。
無論如何,平均確定可以大大簡化(見片段的第二部分)
const arr = [ { name: "John", score: "8.8" }, { name: "John", score: "8.6" }, { name: "John", score: "9.0" }, { name: "John", score: "8.3" }, { name: "Tom", score: "7.9" } ]; // the outer function delivers the inner function // the outer function uses 0, 0 as input initially // The outer function does nothing with those values // and it returns not a value, but the inner function. // The inner function is run every iteration of reduce // and in there the initial closed over values are // manipulated. That inner function returns the actual // accumulator value (a running average) const avgScoreDemo = arr.reduce(function(sum, count) { let outerValues = `outer sum: ${sum}, outer count: ${count}`; return function(avg, person) { console.log(outerValues + ` avg: ${avg}, inner sum ${sum}, inner count: ${count}`); if (person.name === "John") { sum += +person.score; return sum / ++count; } return avg; }; }(0, 0), 0); // This can be simplified to const avgScore = arr.reduce((sum, person) => sum + (person.name === "John"? +person.score: 0), 0) / arr.filter(v => v.name === "John").length; console.log(avgScore); // or using filter/index value const avgScore2 = arr.filter( v => v.name === "John" ).reduce( (acc, person, i) => ({...acc, sum: acc.sum + +person.score, average: (acc.sum + +person.score) / ++i }), { average: 0, sum: 0 } ).average; console.log(avgScore2);
.as-console-wrapper { top: 0; max-height: 100%;important; }
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.