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

JS closure not updating null when passing an object

本文关键字:更新 null 对象 闭包 JS      更新时间:2023-09-26

给定闭包代码,当我传递一个对象时,为什么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();
}

JavaScript中的参数不是通过引用传递的,而是通过一个特殊的"reference-copy"传递的。换句话说,当您将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'

希望有帮助!