Javascript:制作全局变量的本地副本

时间:2015-04-21 05:23:55

标签: javascript

根据this问题,如果我将一个全局变量作为参数传递给函数,那么该全局变量将成为本地副本。

如果是这种情况,为什么this jfiddle的行为方式如此?警报不应该显示dog, cat,而不仅仅是cat

我甚至比示例更进一步,并将全局变量专门复制到局部变量中,但结果是相同的。我真的希望能够在保持全球完整的同时shift()当地人。

任何帮助?

谢谢!

2 个答案:

答案 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副本,但只有在堆上分配的一个对象。
现在,您可以使用该引用来访问对象的成员,并且由于o1o2都包含对同一对象的引用,因此它们将能够定位该对象堆改变它的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