节点内容与对象的功能范围?

时间:2018-03-15 09:09:52

标签: javascript node.js ecmascript-6 scope

我现在正在节点中进行一些编程,我对函数范围的处理感到惊讶。我被引导相信现在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,而不是当它是一个对象时?

3 个答案:

答案 0 :(得分:1)

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

let o1 = {
  a: 1
};
let o2 = o1;

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

答案 1 :(得分:1)

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

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

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

答案 2 :(得分:1)

JavaScript函数pass all arguments 按值

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

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

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

现在,再看看垃圾收集器。删除对before的访问权限。垃圾收集器删除它的值(基本上是指向对象{v:2}的指针)。它可以删除对象本身吗?不,还没有,因为after的值仍指向此对象。但无论如何,两个变量都指向同一个对象。