【问题标题】:Why do objects changed in function change what they point to in memory, but sometimes create a new memory object? [duplicate]为什么功能改变的对象会改变它们在内存中指向的东西,但有时会创建一个新的内存对象? [复制]
【发布时间】:2013-06-26 16:35:20
【问题描述】:

我在this blog 上阅读了有关如果对象或数组在函数内部发生更改,则指向的内存中的值也将被更改,就像在函数外部更改一样。

var a = [1,2,3],
    b = a;

b[0] = 5;
console.log(a); // [5, 2, 3]

结果与

相同
var a = [1,2,3],
    b = a;

var arrayFunction = function(arr){
   arr[0] = 10;
};

var arr = arrayFunction(b);

console.log(a, b, arr) // [10, 2, 3], [10, 2, 3], [10, 2, 3];

但我无法理解的是,为什么在函数内重新分配多个数组值不会改变函数外的值:

var a = [1,2,3],
    b = a;

var arrayFunction = function(arr){
   arr = ["a", "b", "c"];
   return arr;
};

var result = arrayFunction(b);
console.log(result) //["a", "b", "c"]
console.log(a, b);  //[1, 2, 3], [1, 2, 3]

为什么这不会像第一个示例那样改变内存中指向的值?

the JSBIN上写出示例可能会更好

【问题讨论】:

标签: javascript


【解决方案1】:

这是因为 javascript 中的对象并不是真正通过引用传递的。我已经看到它被称为“通过复制引用传递”或“通过句柄传递”——这两者都可以更好地描述真正发生的事情。

在这个例子中:

var b = [1, 2, 3];
var arrayFunction = function(arr) {
   arr = ["a", "b", "c"];
};
arrayFunction(b);

对象引用本身是按值传递的。您实际上并没有更改 b 变量的值。但是,您的函数参数 (arr) 和 b 变量最初指向同一个对象 - 因此,如果您更改其中一个,您可以通过其中一个引用该对象并查看更改。

当您重新分配 arr 以指向不同的对象时,b 变量仍指向旧对象,并且不会改变。

【讨论】:

  • 是的。绝对地。太感谢了。出于某种原因,我没有点击。
【解决方案2】:

请记住,在函数中,arr 不是实际的数组; arr 是指向数组的引用。

所以当您说arr[0] 时,您正在检索数组,然后获取或更新其中的项目。

但是当您说arr = ["a","b","c"] 时,您是在创建一个新对象(在右侧),然后将arr 转换为指向新对象的引用。

【讨论】:

  • 哦。明显地!啊。现在这很有意义。
【解决方案3】:

在 Javascript 中,变量只是 指向 一个数组;所以如果你复制变量,你会得到两个指向同一个数组的变量:

var a = [1,2,3];
var b = a;

使用a[0] = 99 更改数组的元素将可以通过两个变量观察到,因为只有一个数组并且ab 都指向它。

当你改为写作时

a = [5, 6, 7];

您将a 设置为指向另一个不同的数组。

除非您明确提出要求(例如使用b = a.slice()),否则Javascript 永远不会复制数组。

实际上,任何值(例如对象)都会发生同样的情况。对于数字和字符串,同样的逻辑也是有效的,但是很难注意到复制和共享同一对象之间的区别,因为数字和字符串不能更改(“不可变”)。

在 C 和 C++ 等其他语言中,变量包含值,而不是指针;因此,例如在进行赋值时,对象会从一个变量复制到另一个变量,如果您想要一个指针,则必须明确要求它。

【讨论】:

    猜你喜欢
    • 2019-09-05
    • 2018-12-09
    • 2013-12-09
    • 2020-01-11
    • 2023-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-04
    相关资源
    最近更新 更多