根据this问题,如果我将一个全局变量作为参数传递给函数,那么该全局变量将成为本地副本。
如果是这种情况,为什么this jfiddle的行为方式如此?警报不应该显示dog, cat
,而不仅仅是cat
?
我甚至比示例更进一步,并将全局变量专门复制到局部变量中,但结果是相同的。我真的希望能够在保持全球完整的同时shift()
当地人。
任何帮助?
谢谢!
答案 0 :(得分:4)
JS只有pass-by-value。只是想从头开始说清楚 为了简单起见,下面的代码说明了按值传递和传递给参考之间的区别。
<强>通过按值强>
function change (x) { x = 7; }
var x = 1;
change(x);
console.log(x); // 1
pass-by-ref (在JS中不可用)
function change (x) { x = 7; }
var x = 1;
change(x);
console.log(x); // 7
现在,您需要了解某些类型是在堆上分配的,而其他类型是在堆栈上分配的。那是什么意思呢?
好吧,假设你有一个变量。
var x = 5;
这里的值生活在堆栈上。这意味着,如果我这样做
var y = x;
我将在堆栈上有两个变量,都有自己的5
副本
简单类型总是在堆栈上分配。
对象上的 live 。当我这样做时,
var o1 = {x: 5};
对象将在堆上分配,但是o1
变量中的值,它是对堆中对象的引用(让我们调用#ref1
o1
变量中的值),将在堆栈上分配。这意味着,如果我这样做
var o2 = o1;
我将在堆栈上有两个变量,它们都有自己的#ref1
副本,但只有在堆上分配的一个对象。
现在,您可以使用该引用来访问对象的成员,并且由于o1
和o2
都包含对同一对象的引用,因此它们将能够定位该对象堆改变它的x
值。
但是,如果我执行以下操作
o2 = {x: 7};
这将更改存储在堆栈中的变量o2
的值(将调用新值#ref2
)。现在,堆上有两个对象,两个引用存储在堆栈中。
最后,我们来谈谈你的问题:
// the array (which is an object) is allocated on the heap
// {animals} variable will contain a reference to that object (#ref1)
var animals = ["dog", "cat"];
// pass-by-value
pushSearchList(animals);
// local variable {passedAnimals} will contain a copy of #ref1
// but both {passedAnimals} and {animals} can modify the same object
function pushSearchList(passedAnimals){
var localAnimals = passedAnimals;
localAnimals.shift();
alert(animals);
}
现在,如果你想要自己的数组对象副本怎么办?只需使用以下方法克隆数组:
// {arr} will receive reference to a new array allocated on the heap (#ref2)
var arr = passedAnimals.slice(0);
答案 1 :(得分:2)
考虑此代码:
var animals = ["dog", "cat"];
pushSearchList(animals);
function pushSearchList(passedAnimals){
var localAnimals = passedAnimals;
localAnimals.shift();
alert(animals);
}
animals
未复制到该函数。它通过引用传递。您对passedAnimals
ARRAY所做的任何操作也会影响animals
。如果将变量passedAnimals
设置为其他内容,例如自身的副本(即passedAnimals.slice()
),则对新数组的更改将不再影响源。因为数组对象可以更改,所以它们是可变的(容易改变)。
相比之下,另一方面,字符串(虽然它们看起来像一个字符数组)是不可变的(不能改变)。如果将它们传递给参数,则会进行复制。
有关传递价值或参考的更多信息:http://snook.ca/archives/javascript/javascript_pass