简体   繁体   English

JavaScript函数未修改数组(引用?)

[英]Javascript function not modifying array (reference?)

If JavaScript passes a function argument as a reference on the original object, why can´t I modify the original array with this simple function? 如果JavaScript将函数参数作为对原始对象的引用传递,为什么我不能使用此简单函数修改原始数组?

var array1 = ["one"];

function change(array) {
   var array2 = ["222"];
   array = array2;
}

change(array1);

console.log(array1); // this prints ["one"] instead of ["222"]

Why sometimes objects seem to be passed as reference and in this case it´s passed as a copy? 为什么有时对象似乎是作为引用传递的,在这种情况下,它是作为副本传递的?

Because the parameter array isn't the same as array1 . 因为参数arrayarray1 They are separate variables. 它们是单独的变量。 Note that variables are pass-by-value, for objects it's passing a copy of the reference by value. 请注意,变量是按值传递的,对于对象,它按值传递引用的副本 So you would need to do: 因此,您需要执行以下操作:

var array1 = ["one"];

array1 = change(array1);

function change(array) {
   var array2 = ["222"];
   array = array2;
   return array;  
}

console.log(array1);

Why sometimes objects seem to be passed as reference and in this case it´s passed as a copy? 为什么有时对象似乎是作为引用传递的,在这种情况下,它是作为副本传递的?

It's not passed as a copy of the array, it's passed as a copy of the reference to the array. 它不作为数组的副本传递,而是作为对数组引用的副本传递。 There is still only one array, and you can change the array in the function using that reference: 仍然只有一个数组,您可以使用该引用在函数中更改该数组:

var array1 = ["one"];

function change(array) {
   array[0] = "222";
}

change(array1);

console.log(array1); // this prints ["222"]

What you can't do is to replace the array with a different array in the function. 您不能做的就是用函数中的另一个数组替换该数组。 If you assign a new array to the parameter then it will point to the new array, but the variable array1 is still unchanged and points to the original array. 如果为参数分配新数组,则它将指向新数组,但变量array1仍保持不变,并指向原始数组。

The way JavaScript memory storage works is with a stack of Execution Contexts. JavaScript内存存储的工作方式是与一堆执行上下文一起使用。 Each one of these Execution Contexts has a Lexical Environment, and a Variable Environment. 这些执行上下文中的每一个都有一个词汇环境和一个可变环境。

The Lexical Environment is the set of variables that came from all the parent Execution Contexts, for example, the variables saved in the global context will always be available for this reason. 词法环境是来自所有父执行上下文的一组变量,例如,出于这个原因,保存在全局上下文中的变量将始终可用。

The Variable Environment is the set of variables that are being declared in the current Execution Context. 变量环境是在当前执行上下文中声明的变量集。 This is what you are changing in your example, the Variable Environment variable. 这就是您在示例中所要更改的变量环境变量。

function change(array) {
    var array2 = ["222"];
    array = array2;
}

In this example, array is saved in the Variable Environment. 在此示例中, array保存在变量环境中。 Then, array2 is also saved in the Variable Environment. 然后, array2 保存在变量环境中。 As you can see, the Lexical Environment is not changed here at all. 如您所见,词汇环境在这里完全没有改变。 So once execution completes in the function, and control returns, this Execution Context loses scope and is eligible for garbage collection since it has no ties to any Lexical Environments. 因此,一旦在函数中执行完成并返回控件,此执行上下文便失去了作用域,并可以进行垃圾回收,因为它与任何词法环境都没有关系。

That is why the process you used did not replace the array you passed in. You merely replaced a value in the local scope. 这就是为什么您使用的过程没有替换您传入的数组的原因。您仅替换了本地作用域中的一个值。

You can still modify the array passed in and it will change the array itself, but if you assign to that variable then it will no longer be changing the array. 您仍然可以修改传入的数组,它将更改数组本身,但是如果您分配给该变量,则它将不再更改数组。

The reason you see what you see is because all objects in javascript, arrays are considered an object, are passed by reference. 之所以会看到,是因为javascript中的所有对象(数组)都被视为对象,是通过引用传递的。 When you initialize array2 it creates a new place in memory for that array, a new reference. 初始化array2时,它将为该数组在内存中创建一个新位置,即一个新引用。 Then in the change function the parameter array is a reference to array1 but when you set array equal to array2 that variable has had its reference changed to a new spot in memory, the spot where array2 resides. 然后在change函数中,参数array是对array1的引用,但是当您将array设置为array2时,该变量的引用已更改为内存中的新位置,即array2所在的位置。

Fiddle: http://jsfiddle.net/31s3LLjL/1/ 小提琴: http : //jsfiddle.net/31s3LLjL/1/

var array1 = ["one"];
var array2 = ["one"];
var array3 = ["one"];

function change(array) {
   var array2 = ["222"];
   array = array2;
}

function change2(array) {
   array[0] = ["222"];
}

function change3(array) {
   var array2 = array;
   array2[0] = ["222"];
}

change(array1);
change2(array2);
change3(array3);

console.log(array1); // prints one
console.log(array2); // prints 222
console.log(array3); // prints 222

In the first change function we initialize a new array (object). 在第一个change函数中,我们初始化一个新的数组(对象)。 In the other two change functions we only work on the same references to a single place in memory. 在其他两个更改函数中,我们仅对内存中的单个位置使用相同的引用。

The problem is that you indeed have a call by reference, but then change the reference itself inside your function, not the value referred to. 问题是您确实有一个按引用进行调用,但是随后在函数内部更改了引用本身,而不是所引用的值。

What you intended to do is this: 您打算做的是这样的:

var array1 = ["one"];

function change(array) {
   var value = "222";
   array[0] = value;
}

change(array1);

console.log(array1); // this prints ["222"]

A more generic approach would be to use indeed a new array2 inside your function and return (!) that array to the caller. 一种更通用的方法是在函数内部使用新的array2并将该数组返回(!)给调用者。 This is of course not a change of an array in place, but when calling such function, you just assign the returned value back to the original array, and you achieve the same. 当然,这并不是更改数组,而是在调用此类函数时,只需将返回值分配回原始数组,即可实现相同的目的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM