简体   繁体   English

javascript通过引用解决方法传递

[英]javascript pass by reference workaround

let's say I've got an array, var animals = ["dog","cat","rat"]; 假设我有一个数组, var animals = ["dog","cat","rat"];

then I define var pets = animals; 然后我定义var pets = animals;

then I call pets.shift(); 然后我打电话给pets.shift();

now because javascript is pass-by-reference for arrays, if I now call animals , I get ["cat","rat"] . 现在因为javascript是数组的传递引用,如果我现在调用animals ,我得到["cat","rat"]

My question: is there any way around this, if I would later like to use animals in its unmodified form? 我的问题:如果我以后想以未经修改的形式使用animals ,有什么方法吗?

A note on terminology: JavaScript is never pass-by-reference (no matter how many times you hear people say that it is). 关于术语的说明:JavaScript 永远不会 通过引用传递 (无论你听到有多少人说过它)。 When you write the line: 写行时:

var pets = animals;

You're assigning the value of animals to pets . 你正在为pets分配animals价值 The value that is assigned is a reference to an array, so now both variables refer to the same object in memory. 分配的值是对数组的引用,因此现在两个变量都引用内存中的同一对象。 (Note: this is a bit pedantic, but it also has the nice property of being correct .) (注意:这有点迂腐,但它也有正确的好处 。)

If you want these two variables to refer to two different arrays, then you need to create a copy of the original array and assign a reference to that to pets . 如果您希望这两个变量引用两个不同的数组,那么您需要创建原始数组的副本并为pets分配对它的引用。 The most common way to do that in JavaScript is to take advantage of the fact that some array methods (like slice or concat ) create a copy of the array on which they're called: 在JavaScript中最常用的方法是利用一些数组方法(如sliceconcat )创建调用它们的数组的副本这一事实:

var pets = animals.concat();

Proof of in/equality: in / equality的证明:

var arr = [];
arr1 = arr;
console.log(arr1 === arr); // true
console.log(arr1 === arr.concat()) // false

Of course, you can also perform the copy yourself: 当然,您也可以自己执行复制:

function copy(arr) {
    var i, len = arr.length, arr1 = new Array(len);
    for (i = 0; i < len; i += 1) {
        arr1[i] = arr[i];
    }
    return arr1;
}

Indeed, this is probably a lot faster and should be considered for very large arrays. 实际上, 这可能要快得多 ,应该考虑用于非常大的阵列。 (In most cases, just do whatever is most readable.) (在大多数情况下,只做最可读的事情。)

Note that each of these methods creates a shallow copy of the original array. 请注意,这些方法中的每一个都会创建原始数组的浅表副本。 If the array holds references to other objects, then those references are copied to the new array (ie both the original and the new array will refer to the same objects). 如果数组保存对其他对象的引用,则将这些引用复制到新数组(即原始数组和新数组都将引用相同的对象)。 Strings and numbers, on the other hand, are copied directly into the new array. 另一方面,字符串和数字将直接复制到新数组中。

You have to clone the array, which is done with 你必须克隆数组,这是完成的

var savedAnimals = animals.slice();

Note that this isn't a deep clone : it doesn't protect the elements inside against modification (if they're not strings). 请注意,这不是深度克隆:它不保护内部元素不受修改(如果它们不是字符串)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM