关于javascript:节点ints与对象的函数范围?

Function scope in node ints versus objects?

本问题已经有最佳答案,请猛点这里访问。

最近我在node中做了一些编程,我对函数中作用域的处理有点惊讶。我相信现在ES6的范围要严格得多。预期的工作如下:

1
2
3
4
5
6
7
8
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)

但当我使用对象/字典执行相同操作时,变量的范围似乎超出了函数的范围:

1
2
3
4
5
6
7
8
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)

这到底是为什么?为什么当它是一个int时,v的作用范围仅限于它的功能,而当它是一个对象时,则不限于它的作用范围?


javascript函数按值传递所有参数。

在第一种情况下,您有一个原语值(数字是原语)。因此,before是指原语值1。你把它传进来-它是按值传的。返回一个值。将其分配给第二个对象。after是另一个对象。基本上,两个指针指向不同的对象。不同的对象。不同的值。

从垃圾收集的角度来考虑。你失去了"之前"超出你的范围。无法再访问1原语。免费打扫。

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

现在,再一次,看看垃圾收集器。删除对before的访问。垃圾收集器移除它的值(基本上是指向对象v:2的指针)。它能移除对象本身吗?还没有,因为EDOCX1[1]的值仍然指向这个对象。但不管怎样,两个变量都指向同一个对象。


Javascript有两种数据类型:Primitive和Object。

在第一个示例中,您传递的是一个基本数据类型(布尔值、空值、未定义、字符串、符号和数字——您的大小写)。当您将这些类型的变量传递给一个函数时,您将传递一个副本——所以任何修改都不会影响初始值/变量,就像在第一个例子中一样。

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


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

1
2
3
4
5
6
7
let o1 = {
  a: 1
};
let o2 = o1;

o1.a++;
console.log(o2);