麻省理工学院开放课程中的JavaScript示例

麻省理工学院开放课程中的JavaScript示例,javascript,Javascript,有人能解释一下这是如何得到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的,以及算法是如何工作的吗。谢谢

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

你能修好它吗

资料来源:


第30页

此代码创建了一个函数数组,这些函数最终都会错误地引用i的最终值,但其目的是在每次迭代期间冻结i的值

要解决这个问题,您只需通过嵌入一个新的局部变量,将i的值冻结在另一个函数中,向迭代变量添加一个局部性级别。例如,在下面,现有局部变量i作为参数传递到伪函数中,此时i的值被冻结到新的局部变量i中,该局部变量i独立于原始i,并且不会因原始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在a中的所有函数中共享,闭包就是这样做的——它们共享堆栈帧。你可以通过打破闭包来防止这种情况。你可以随意称呼它。在这种情况下,i的范围产生了不想要的结果。但是你不能用闭包来阻止它——闭包是你范围问题的根源。你可以通过打破封口来防止它。你通过传递函数参数来打破一个闭包。你实际上是在限定i的范围,因为你是在把这个参数传递到一个自动执行的函数中,在这个函数中它被关闭了。我读过的多本书教会了我这一点。我自己从来没有听说过这种打破封闭条件的做法。是的,这正是它所做的。但是,这种机制不称为闭包。闭包是导致我首先被共享的机制。您对i的范围界定旨在将其从闭包中移除。请参阅:
function multipliers(max){
  var a = [];
  for(var i=0; i<max; i++){
    (function(i){
      a.push(function(x){return x*i});
    })(i);
  }
  return a;
}
console.log(multipliers(10)[2](5));