在 JavaScript 中制作全局变量的本地副本

cro*_*ill 2 javascript

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

如果是这样,为什么这个 jfiddle 的行为方式如此?警报dog, cat不应该显示而不仅仅是显示cat吗?

我什至比示例更进一步,专门将全局变量复制到局部变量中,但结果是一样的。我真的很希望能够shift()在保持全局完整的同时进行本地化。

小智 6

JavaScript 只有按值传递。我只是想从一开始就说清楚。

为了简单起见,下面的代码说明了pass-by-valuepass-by-reference之间的区别。

传值

function change (x) { x = 7; }

var x = 1;
change(x);
console.log(x); // 1
Run Code Online (Sandbox Code Playgroud)

传递引用(在 JavaScript 中不可用)

function change (x) { x = 7; }

var x = 1;
change(x);
console.log(x); // 7
Run Code Online (Sandbox Code Playgroud)

现在,您需要了解一些类型分配在堆上,而其他类型分配在堆栈上。那是什么意思呢?

好吧,假设您有一个变量。

var x = 5;
Run Code Online (Sandbox Code Playgroud)

这里的值存在于堆栈中。这意味着,如果我这样做

var y = x;
Run Code Online (Sandbox Code Playgroud)

我将在堆栈上有两个变量,它们都有自己的5. 简单类型总是在堆栈上分配。

另一方面,对象存在于堆中。当我做,

var o1 = {x: 5};
Run Code Online (Sandbox Code Playgroud)

对象将在堆上分配,但o1变量中的值,即对堆中对象的引用(我们称之为变量中#ref1的值o1),将在堆栈上分配。这意味着,如果我这样做

var o2 = o1;
Run Code Online (Sandbox Code Playgroud)

我将在堆栈上有两个变量,它们都有自己的 副本#ref1,但在堆上分配了一个对象。

现在,您可以使用引用访问对象的成员,因为两者o1o2包含对同一对象的引用,他们就能找到对象堆中的变化它的x价值。但是,如果我执行以下操作

o2 = {x: 7};
Run Code Online (Sandbox Code Playgroud)

这将更改存储在堆栈中的变量值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);
}
Run Code Online (Sandbox Code Playgroud)

现在,如果您想要自己的数组对象副本怎么办?只需使用以下命令克隆数组:

// {arr} will receive reference to a new array allocated on the heap (#ref2)
var arr = passedAnimals.slice(0);
Run Code Online (Sandbox Code Playgroud)