传递对象时,JS闭包不会更新null

时间:2015-05-26 23:55:08

标签: javascript

给定带闭包的代码,为什么make_function在传递对象时返回null

Plnkr:http://plnkr.co/edit/L3nNeiibTMdR6GEnyMOX?p=preview

$(document).ready(everything);

function everything() {

  var null_start = null;
  var object_start = { obj: null };

  function make_function (arg) {
    return function () {
      d3.select('#console')
        .append('p')
        .text(JSON.stringify(arg))
        .style('color', 'blue');
    };
  }

  // Make a function with arg=null
  var func = make_function(null_start);
  d3.select('#console').append('p').text('Expecting null here');
  func();

  null_start = {
    foo: 5,
    bar: 42
  };
  d3.select('#console').append('p')
    .html('Expecting {foo:5, bar:42} here <span style="color:red;">Why is this still null???</span>');
  func();

  // Make a function with arg={obj:null}
  func = make_function(object_start);
  d3.select('#console').append('p').text("Expecting {obj: null} here");
  func();

  object_start.obj = {
    foo: 5, 
    bar: 42
  };
  d3.select('#console').append('p')
    .html('Expecting {obj: {foo:5, bar:42}} here <span style="color:red;">if this one is updated?</span>');
  func();
}

1 个答案:

答案 0 :(得分:3)

JavaScript中传递的参数不是通过引用传递的,而是通过特殊的“引用副本”传递的。换句话说,当您将null_start传递给make_function时,会传递null_start变量的副本。

null_start变量的更改会被传递给函数的变量反映出来。

这就是为什么使用变量的新值创建另一个函数的方法与示例中的预期一致。

请注意,在传递对象时,对象的更改也将由原始变量反映。这是因为JavaScript中的对象是可变的。例如:

function change (obj) { obj.foo = 'bar'; }
var x = {};
change(x);
console.log(x.foo); // 'bar'

这是因为对象只是一组指向值的键。对象内的键指向到值,可以修改这些值,并由函数的外部范围反映出来。但是,如果我们直接传递该值,它将无法工作:

function change (val) { val = 'fff'; }
var x = {foo: 'bar'};
change(x.foo);
console.log(x.foo); // 'bar'

希望有所帮助!