我有可能是一个愚蠢的问题。在下面的代码中,函数doStuff似乎将myArray重新分配给一个空数组,但是当在控制台中尝试它时,myArray仍然是[2,3,4,5]。
var myArray = [2, 3, 4, 5];
function doStuff(arr) {
arr = [];
};
doStuff(myArray);
console.log(myArray)// => [2,3,4,5]
此外,修改数组的函数似乎工作正常。例如:
function changeSecondIndex(arr){
arr[2] = 25;
}
changeSecondIndex(myArray)
console.log(myArray) // => [2,3,25,5]
有人可以帮我理解这里发生了什么吗?感谢。
答案 0 :(得分:4)
您的代码正在创建新的空数组,而您可以使用length = 0
var myArray = [2, 3, 4, 5];
function doStuff(arr) {
arr.length = 0;
};
doStuff(myArray);
console.log(myArray)
答案 1 :(得分:3)
Javacript数组是passed by reference,这意味着它们可以在函数内修改。这就是您的第二个代码段有效的原因。
然而,您的第一个代码段只是在函数范围内声明 new 变量arr
。它不会覆盖旧的变量名,它只会删除您引用传入的全局变量的能力。
一旦该函数退出,新变量arr
超出范围,名称绑定将回退到您之前声明的全局变量。
这就是为什么doStuff()
不会修改原始数组的原因 - 因为您实际上声明了一个刚刚在函数范围内共享相同名称的全新数组。
答案 2 :(得分:3)
数组在JavaScript中由引用传递。因此,在doStuff
和changeSecondIndex
函数中,arr
参数包含引用到myArray
。
在changeSecondIndex
中,您使用该引用来访问和更新数组的属性。你可以看到,这很好。但在doStuff
中,实际发生的是您将arr
设置为新数组。这样做是为了删除arr
是对myArray
的引用并将其设置为新的空白数组的事实。这就是myArray
未被修改的原因。
答案 3 :(得分:2)
对象在JavaScript中通过引用传递,当您在第一个示例中调用该函数时,参数arr
是对调用函数时传递的对象的引用
var myArray = [2, 3, 4, 5];
function doStuff(arr) {
//arr is a variable that contains the first parameter used to invoke the
//function, if the variable is an object then it is passed by reference
//
//Here you are assigning the variable "arr" the value of a new array
arr = [];
};
doStuff(myArray);
console.log(myArray)// => [2,3,4,5]
在第二个示例中,您正在修改传递的对象,所有内容仍然以相同的方式传递,不同之处在于您正在对传递的对象进行操作,而不是为变量分配新值。
function changeSecondIndex(arr){
//Acting on index 2 of the passed array and setting the value to 25
arr[2] = 25;
}
changeSecondIndex(myArray)
console.log(myArray) // => [2,3,25,5]
如果你想做一些类似于你在第一个例子中尝试做的事情,那么可能会有一些包含变量状态的对象
var workingVars= {arr: [2, 3, 4, 5]};
function doStuff(env) {
// here you are assigning a new empty array to arr property of
// passed parameter
env.arr = [];
};
doStuff(workingVars);
console.log(workingVars.arr)// => []
答案 4 :(得分:1)
你不需要一个函数和参数来试验这个。在JS []
和{}
中是对象创建模式(文字)并打破引用。我们来看看......
var a = [1,2];
var b = [2,4];
var c = a; // c references a array.
var d = b; // d references b array
a.length = 0; // a becomes []
b = []; // b becomes []
console.log(c); // [] c still references a
console.log(d); // [2,4] d is no more a reference to b
当然这同样适用于对象;
var o1 = {x:1, y:2};
var o2 = {x:2, y:4};
var p1 = o1; // p1 references o1
var p2 = o2; // p2 references o2
delete o1.x;
delete o1.y;
console.log(o1); // Object {}
console.log(p1); // Object {} p1 still references o1
o2 = {};
console.log(o2); // Object {}
console.log(p2); // Object {x: 2, y: 4} p2 is no more a reference to o2
答案 5 :(得分:0)
要理解为什么会发生这种情况,您必须首先记住Javascript中的数组是一个对象。您的arr = []
对您的全局声明不起作用的原因如下:
原因1:
arr = []
无法清除数组,只需在内存中创建一个新的数组对象,无论如何。
所以在你的功能中:
function doStuff(arr) {
arr = [];
};
doStuff(myArray)
你只是接受myArray 并在本地范围内创建一个新的空版本,这导致了原因2.
原因2:
在函数中声明的任何新对象/变量仅限于该函数的本地范围
所以:
function doStuff(arr) {
arr = [];
};
doStuff(myArray) //logs [1,2,3,4]
arr = []
在doStuff函数的右括号处被销毁,外部不存在。
原因3:
function doStuff(arr){
arr[2] = 25;
}
doStuff(myArray)
这是有效的,因为您在arr变量中访问myArray并修改了myArray对象的属性,这在javascript中完全正常。
简而言之:
=
运营商分配,重新分配,创建 s ...
arr = []
是您的函数中对新myArray对象的赋值,也被困在函数范围内。
arr[2] = 25
暂时访问myArray对象并重新分配属性。
希望这会有所帮助..
答案 6 :(得分:-4)
您已定义全局var myArray。然后你想要访问这个全局数组并在功能上进行更改。是的,它将覆盖全局数组,但仅限于您具体的功能。在你的情况下函数doStuff()。
如果你不调用doStuff(),它将保持全局的inicialization值!