来自麻省理工学院公开课程的JavaScript示例

JavaScript example from MIT open course

本文关键字:JavaScript 示例 麻省 理工学院      更新时间:2023-09-26

有人可以解释一下它是如何得到 50 的,以及算法是如何工作的。谢谢。

var multipliers = function makeMultipliers (max) { 
    var result = [];
    for (var i = 0; i < max; i++)
        result.push (function (x) {return x * i;}); 
    return result;
}
multipliers(10) [2] (5)
???

价值是什么?

50,而不是 5

你能解决它吗?

来源:http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-170-software-studio-spring-2013/lecture-notes/MIT6_170S13_35-java-fn-cls.pdf

第 30 页

这是一个范围问题。到调用最后一个函数时,i是最后一次在该作用域看到它的位置,即 10。您可以通过关闭来防止这种情况。

function multipliers(max){
  var a = [];
  for(var i=0; i<max; i++){
    (function(i){
      a.push(function(x){return x*i});
    })(i);
  }
  return a;
}

在这种情况下,闭包是一个自执行函数,它在循环的每一步都限定i范围。如果没有发生这种情况,则范围将转到multipliers函数本身。由于在您调用5传递到的函数时,循环已经完成,该函数恰好位于multipliers返回的数组的第 2 步,因此i已经到达10。显然,10*5 是 50。当使用闭包时i最后一个位置2在其所在的范围内,从而为您提供所寻求的结果。5*2 = 10。

console.log(multipliers(10)[2](5));

这段代码创建了一个函数数组,这些函数将错误地全部引用i的最终值,但旨在冻结每次迭代期间i的值。

要修复它,您只需通过嵌入一个新的局部变量来冻结另一个函数中的i值,从而为迭代变量添加一定程度的局部性。例如,在现有局部变量下方,i作为参数传递到虚拟函数中,并且该时刻的i值被冻结到新的局部变量i中,该变量独立于原始i,并且不会因原始i的后续迭代而更改。

result.push (function (x) {return x * i;})
result.push((function(i) {
    return function (x) {return x * i;};
})(i));