如何避免在JavaScript函数中制作函数的浅表副本?

时间:2013-11-19 13:44:49

标签: javascript deep-copy

我正在尝试用JavaScript编写符号处理计算器。我遍历一个符号列表。我的样本输入是1 + 2。

for <every element in the list> {
    ...
    // this case handles simple numbers
    var tmp = o.val;
    list[pos] = {type: 'expression', val: +tmp, calc: function (x) {return +tmp} };

    ...
    // this case handles addition
    var v1 = list[pos-1].val, v2 = list[pos+1].val;
    var f1 = list[pos-1].calc, f2 = list[pos+1].calc;
    list[pos-1] = {type: 'expression', val: v1 + ' + ' + v2, calc: function (x) {return f1(x) + f2(x)} };
    ...
}
alert(list[0].val + '=' + list[0].calc(0));

问题是这显示4而不是3.对第一个操作数的calc()调用不再返回1但是2.我希望'calc'保存当前值,以制作深度副本f1和f2的功能。我该如何实现这一目标?什么是好的编程实践?

2 个答案:

答案 0 :(得分:1)

虽然已经链接了正确的解释,但这是解决问题的简单方法:您必须打开一个新的变量范围,以确保每次“tmp”实际上是一个新变量,而不是相同的变量一遍又一遍:

for <every element in the list> {
  (function() {
    ... loop body ...
  )();
}

答案 1 :(得分:0)

您的问题可以简化为:

var funcs = [];
for (var i=0; i<2; i++) {
  var temp = i;
  funcs.push(function() { console.log(temp) });
}

funcs[0](); // 1  - expected 0
funcs[1](); // 1

问题是你的函数会在temp上创建一个闭包。它们处理实际的临时变量,而不是定义它们时临时变量值的副本。

解决方案很简单:创建临时变量的副本(通过将其作为参数传递给函数):

var funcs = [];
for (var i=0; i<2; i++) {
  var temp = i;
  funcs.push(function(copy) { // anonymous function that copies temp
      return function() { console.log(copy); }
    }(temp) // call the anonymous function
  );
}

funcs[0](); // 0
funcs[1](); // 1