Javascript 多次将数组传递给函数
我正在学习javascript,并试图弄明白为什么我的下面的函数不能按预期工作。请参见2个代码示例中的说明:Javascript 多次将数组传递给函数,javascript,Javascript,我正在学习javascript,并试图弄明白为什么我的下面的函数不能按预期工作。请参见2个代码示例中的说明: // First time I call the shoplist function I pass [1] in the argument. Results are as I expect: var shopitems = []; function shoplist(ids) { alert("ids passed to shoplist function: " + ids)
// First time I call the shoplist function I pass [1] in the argument. Results are as I expect:
var shopitems = [];
function shoplist(ids) {
alert("ids passed to shoplist function: " + ids); // 1
alert("current ids in shopitems var: " + shopitems); // (empty)
shopitems.push(ids);
alert("ids in shopitems after pushing: " + shopitems); // 1
}
// Second time I call the shoplist functions I pass [1, 2] in the argument. Results are not what I would expect:
function shoplist(ids) {
alert("ids passed to shoplist function: " + ids); // 1, 2
alert("current ids in shopitems var: " + shopitems); // 1, 2 <--- Why is there 1, 2 and not only 1?
shopitems.push(ids);
alert("ids in shopitems after pushing: " + shopitems); // 1, 2, 1, 2
//第一次调用shoplist函数时,我在参数中传递[1]。结果如我所料:
var shopitems=[];
功能购物清单(ids){
警报(“传递给shoplist函数的ID:+ids);//1
警报(“shopitems变量中的当前ID:+shopitems);//(空)
shopitems.push(ID);
警报(“推送后shopitems中的ID:+shopitems);//1
}
//第二次调用shoplist函数时,我在参数中传递[1,2]。结果并非我所期望的:
功能购物清单(ids){
警报(“传递给shoplist函数的ID:+ids);//1,2
警报(“shopitems var:+shopitems中的当前ID”);//1,2如果在调用第二次调用shoplist()之前修改相同的ID数组,则会出现问题
。由于javascript通过引用传递数组,并且只有一个引用进入shopitems
数组,因此当您在将ids数组传递给shoplist()
的第二个调用之前修改它时,您也无意中修改了shopitems[0]
。如果shoplist()的每个参数
第一次和第二次调用时,它是完全独立的数组,不会出现此问题,但如果第二次调用只是传递了对第一个数组的修改,则会出现此问题
快速说明如下:
// this will not have the problem because each call to shoplist
// is passing a completely separate array
var list = [1];
shoplist(list);
list = [1,2]; // create new array
shoplist(list); // shoplist is [[1], [1,2]]
// this will have the problem because they are the same array
var list = [1];
shoplist(list);
list.push(2); // modify first array
shoplist(list); // shoplist is [[1,2], [1,2]] and both array elements are actually the same array
有关详细说明:.push(ids)
在shopitems
数组的末尾添加一个新项目,无论ids
的内容如何。因此,每次调用shoplist时,您都会在shopitems的末尾获得一个新项目。但是,由于您添加的项目是一个数组,因此它会添加对该数组的引用,而不是该数组的副本。如果您随后更改该数组,shopitems数组条目将指向数组的更改版本
您可以在该代码中看到:
var x = [];
var list = [];
x.push(1); // contains contains [1]
list.push(x); // list is [[1]]
x.push(2); // x is [1,2]
list.push(x); // list is [[1,2], [1,2]] (contains two references to x)
在此代码示例中,列表将包含两个元素,每个元素将指向相同的x
实时版本,其中包含[1,2]
这是因为默认情况下,javascript传递数组和对象之类的引用。当您将数组元素推入容器数组时,它不是将该变量的静态副本放入数组中。而是将指针放入原始变量。如果您随后更改原始变量,则该更改将反映在数组中我也是
要将第二个条目与第一个条目分开,您需要有意识地创建第一个数组的副本并将该副本推送到容器数组中,或者需要从头创建一个新数组并将其推送到容器数组中
例如,以下是在容器数组中创建两个独立元素的几种方法:
var x = [];
var list = [];
x.push(1); // contains contains [1]
list.push(x); // list is [[1]]
x = []; // set x to a new array (the old version of x is still in list)
x.push(1); // x is [1]
x.push(2); // x is [1,2]
list.push(x); // list is [[1], [1,2]] (contains two separate items)
或者,复制一份x
:
var x = [];
var list = [];
x.push(1); // contains contains [1]
list.push(x); // list is [[1]]
x = x.slice(0); // make a copy of x, the old version of x is still in list
x.push(1); // x is [1]
x.push(2); // x is [1,2]
list.push(x); // list is [[1], [1,2]] (contains two separate items)
这里需要记住的重要一点是,在javascript中,对象分配或数组分配不会生成副本。它只会分配一个指向原始数据结构的指针。如果更改原始数据结构,这将反映在所做的任何分配中
如果要创建副本,则必须显式创建新数组或显式创建副本。如果在调用第二次调用shoplist()之前修改相同的ids数组,则会出现问题
。由于javascript通过引用传递数组,并且只有一个引用进入shopitems
数组,因此当您在将ids数组传递给shoplist()
的第二个调用之前修改它时,您也无意中修改了shopitems[0]
。如果shoplist()的每个参数
第一次和第二次调用时,它是完全独立的数组,不会出现此问题,但如果第二次调用只是传递了对第一个数组的修改,则会出现此问题
快速说明如下:
// this will not have the problem because each call to shoplist
// is passing a completely separate array
var list = [1];
shoplist(list);
list = [1,2]; // create new array
shoplist(list); // shoplist is [[1], [1,2]]
// this will have the problem because they are the same array
var list = [1];
shoplist(list);
list.push(2); // modify first array
shoplist(list); // shoplist is [[1,2], [1,2]] and both array elements are actually the same array
有关详细说明:.push(ids)
在shopitems
数组的末尾添加一个新项目,无论ids
的内容如何。因此,每次调用shoplist时,您都会在shopitems的末尾获得一个新项目。但是,由于您添加的项目是一个数组,因此它会添加对该数组的引用,而不是该数组的副本。如果您随后更改该数组,shopitems数组条目将指向数组的更改版本
您可以在该代码中看到:
var x = [];
var list = [];
x.push(1); // contains contains [1]
list.push(x); // list is [[1]]
x.push(2); // x is [1,2]
list.push(x); // list is [[1,2], [1,2]] (contains two references to x)
在此代码示例中,列表将包含两个元素,每个元素将指向相同的x
实时版本,其中包含[1,2]
这是因为默认情况下,javascript传递数组和对象之类的引用。当您将数组元素推入容器数组时,它不是将该变量的静态副本放入数组中。而是将指针放入原始变量。如果您随后更改原始变量,则该更改将反映在数组中我也是
要将第二个条目与第一个条目分开,您需要有意识地创建第一个数组的副本并将该副本推送到容器数组中,或者需要从头创建一个新数组并将其推送到容器数组中
例如,以下是在容器数组中创建两个独立元素的几种方法:
var x = [];
var list = [];
x.push(1); // contains contains [1]
list.push(x); // list is [[1]]
x = []; // set x to a new array (the old version of x is still in list)
x.push(1); // x is [1]
x.push(2); // x is [1,2]
list.push(x); // list is [[1], [1,2]] (contains two separate items)
或者,复制一份x
:
var x = [];
var list = [];
x.push(1); // contains contains [1]
list.push(x); // list is [[1]]
x = x.slice(0); // make a copy of x, the old version of x is still in list
x.push(1); // x is [1]
x.push(2); // x is [1,2]
list.push(x); // list is [[1], [1,2]] (contains two separate items)
这里需要记住的重要一点是,在javascript中,对象分配或数组分配不会生成副本。它只会分配一个指向原始数据结构的指针。如果更改原始数据结构,这将反映在所做的任何分配中
如果要复制,则必须显式创建新数组或显式创建副本。我运行了此代码
var shopitems = [];
shoplist([1]);
shoplist([1,2]);
function shoplist(ids) {
WScript.Echo("ids passed to shoplist function: " + ids); // 1
WScript.Echo("current ids in shopitems var: " + shopitems); // (empty)
shopitems.push(ids);
WScript.Echo("ids in shopitems after pushing: " + shopitems); // 1
}
得到了这个输出
ids passed to shoplist function: 1
current ids in shopitems var:
ids in shopitems after pushing: 1
ids passed to shoplist function: 1,2
current ids in shopitems var: 1
ids in shopitems after pushing: 1,1,2
在我看来,它运行得很好。我运行了这个c