1

我在这个博客上读到,如果一个对象或数组在函数内部发生了变化,那么所指向的内存中的值也会发生变化,就像它在函数外发生变化一样。

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]

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

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

4

3 回答 3

3

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

在这个例子中:

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

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

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

于 2013-06-28T19:53:15.030 回答
2

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

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

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

于 2013-06-28T19:53:35.903 回答
1

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

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

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

当你改为写

a = [5, 6, 7];

您正在设置a指向另一个不同的数组。

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

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

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

于 2013-06-28T20:01:18.363 回答