【问题标题】:Function scope in node ints versus objects? [duplicate]节点整数与对象中的函数范围? [复制]
【发布时间】:2018-08-24 00:25:41
【问题描述】:

这些天我在 node 中做一些编程,我对函数中范围的处理感到有点惊讶。我被引导相信现在使用 ES6 范围要严格得多。以下按预期工作:

function f(v){
    v += 1;
    return v;
}
let before = 1;
let after = f(before);
console.log(after);  // This logs 2 (as expected)
console.log(before);  // This logs 1 (as expected)

但是当我使用对象/字典做同样的事情时,变量的范围似乎超出了函数:

function f(v){
    v.a += 1;
    return v;
}
let before = {a: 1};
let after = f(before);
console.log(after.a);  // This logs 2 (as expected)
console.log(before.a);  // This also logs 2 (I was expecting this to still be 1)

到底为什么会这样?为什么v的作用域是int时只限于函数,而当它是对象时则不是?

【问题讨论】:

  • 这似乎是原始数据类型与对象的情况。类似的事情会在 Java 中发生 ints vs. Strings
  • 在 JS 中,只有字符串和数字是通过值传递的,其他的都是通过引用/指针传递的。它与 ES6 无关。
  • @t.niese 类似的东西。不复制对象。但是被复制的是对这些对象的引用。所以,beforeafter 是不同的引用,但它们具有相同的 value:对象本身的地址。
  • @FisNaN 如果您使用术语 referencepointer,则需要小心。通过引用传递在 js 中并不真正存在,至少在 function test(a) { a = {foo:1} } test(b); console.log(b.foo) 可以工作的意义上不存在。
  • @Zlatko 是的,我知道。但我没有时间(或者说老实说动机)用正确的术语写一个答案。 :) 至此,这只是一个评论。但是您的回答很好地说明了这一点。

标签: javascript node.js ecmascript-6 scope


【解决方案1】:

Javascript 有两种数据类型:原始和对象。

在您的第一个示例中,您传递的是 primitive 数据类型(布尔、空、未定义、字符串、符号和数字 - 您的情况)。当您将这些类型的变量传递给函数时,您传递的是一个副本 - 因此任何修改都不会影响初始值/变量,就像在第一种情况下一样。

对于 Object 数据类型,当您将一个对象传递给一个函数时,您传递的是对该对象值的引用,而不是该值的副本,就像原语一样。因此,当您在函数中修改它时,您正在修改引用。这意味着任何具有此引用的变量也将具有修改后的值,因为它们只是指向最近修改过的值。

【讨论】:

    【解决方案2】:

    JavaScript 函数 pass all arguments 按值

    在第一种情况下,您有一个原始值(数字是原始的)。所以,before 指的是一个原始值,值为 1。您将它传入 - 它是通过 按值 传递的。你返回一个值。将其分配给第二个对象。 after 是另一个对象。基本上,两个指针,指向不同的对象。不同的对象。不同的值。

    从垃圾收集的角度来考虑它。你失去了“之前”的范围。 1 原语不再可访问。免费清理。

    在第二种情况下,您传递一个对象引用的值。然后你再次返回对象引用的值。所以beforeafter 指的是同一个对象。它们是不同的参考。因此,在 console.log(before)console.log(after) 中,您引用的是相同的对象和相同的(现已修改)值。

    现在,再次查看垃圾收集器。删除对before 的访问权限。垃圾收集器删除它的值(基本上是指向对象 {v: 2} 的指针)。它可以删除对象本身吗?不,还没有,因为after 的值仍然指向这个对象。但不管怎样,两个 var 都指向同一个对象。

    【讨论】:

      【解决方案3】:

      这里的范围没有错。 您的代码只是将一个对象分配给另一个变量,因此每当您编辑对象时,所有分配的变量都会受到影响:

      let o1 = {
        a: 1
      };
      let o2 = o1;
      
      o1.a++;
      console.log(o2);

      【讨论】:

      • 没有解释参考与价值这个答案很不完整
      猜你喜欢
      • 2014-11-01
      • 1970-01-01
      • 2012-09-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多