我写了以下JavaScript:
var myArray = ['a', 'b', 'c'];
var copyOfMyArray = myArray;
copyOfMyArray.splice(0, 1);
alert(myArray); // alerts ['b','c']
alert(copyOfMyArray); // alerts ['b','c']
var myNumber = 5;
var copyOfMyNumber = myNumber;
copyOfMyNumber = copyOfMyNumber - 1;
alert(myNumber); // alerts 5
alert(copyOfMyNumber); // alerts 4
此代码声明变量myArray
并将其设置为数组值。然后它声明第二个变量copyOfMyArray
并将其设置为myArray
。
它会对copyOfMyArray
执行操作,然后向myArray
和copyOfMyArray
发出警报。不知何故,当我在copyOfMyArray
上执行操作时,似乎在myArray
上执行了相同的操作。
然后代码使用数字值执行相同的操作:它声明变量myNumber
并将其设置为数字值。然后它声明第二个变量copyOfMyNumber
并将其设置为myNumber
。它会对copyOfMyNumber
执行操作,然后向myNumber
和copyOfMyNumber
发出警报。在这里,我得到了预期的行为:myNumber
和copyOfMyNumber
的不同值。
数组和JavaScript中的数字有什么区别,似乎更改数组会更改数组副本的值,而更改数字不会更改数字副本的值?
我猜测由于某种原因,数组是通过引用和数字引用的,但为什么呢?我如何知道其他对象的行为?
答案 0 :(得分:90)
JavaScript中的数组也是对象,变量只将引用保存到对象,而不是对象本身。因此,两个变量都引用相同的对象。
您与数字示例的比较不正确顺便说一下。您为copyOfMyNumber
分配了一个新值。如果您为copyOfMyArray
分配新值,则不会更改myArray
。
您可以使用slice
[docs]创建数组的副本:
var copyOfMyArray = myArray.slice(0);
但请注意,这只返回浅副本,即不会克隆数组中的对象。
答案 1 :(得分:20)
嗯,唯一可能的答案 - 也就是正确的答案 - 就是你实际上没有复制数组。当你写
var copyOfArray = array;
您将引用分配给同一个数组到另一个变量中。换句话说,他们都指向同一个物体。
答案 2 :(得分:10)
所以这里的每个人都做了很好的解释为什么正在发生的事情 - 我只是想放弃一条线让你知道 如何 我能够解决这个问题 - 非常容易:
thingArray = ['first_thing', 'second_thing', 'third_thing']
function removeFirstThingAndPreserveArray(){
var copyOfThingArray = [...thingArray]
copyOfThingArray.shift();
return copyOfThingArray;
}
这是使用...传播语法。
编辑:至于为什么,并回答你的问题:
数组和JavaScript中的数字有什么区别,似乎更改数组会更改数组副本的值,而更改数字不会更改数字副本的值?
答案是在JavaScript中,数组和对象是 mutable ,而字符串和数字以及其他基元是 immutable 。当我们执行如下任务时:
var myArray = ['a', 'b', 'c']; var copyOfMyArray = myArray;
copyOfMyArray实际上只是对myArray的引用,而不是实际的副本。
我会建议这篇文章What are immutable and mutable data structures?深入研究这个主题。
答案 3 :(得分:7)
我发现这是对对象或数组进行深度克隆的最简单方法:
const objectThatIWantToClone = { foo: 'bar'};
const clone = JSON.parse(JSON.stringify(objectThatIWantToClone));
通过字符串化,我们制作一个不可变的副本,然后我们可以将其转换回JSON。
答案 4 :(得分:5)
克隆对象 -
loop / array.push
会产生与array.slice(0)
或array.clone()
类似的结果。值都是通过引用传递的,但由于大多数原始数据类型都是 immutable ,因此后续操作会产生所需的结果 - “克隆”。当然,对象和数组不是这样,它允许修改原始引用(它们是可变类型)。
采用以下示例:
const originalArray = [1, 'a', false, {foor: 'bar'}]
const newArray = [];
originalArray.forEach((v, i) => {
newArray.push(originalArray[i]);
});
newArray[0] = newArray[0] + 1;
newArray[1] = 'b';
newArray[2] = true;
newArray[3] = Object.assign(newArray[3], {bar: 'foo'});
在newArray索引上运行的操作都会产生所需的结果,但final(object)除外,因为它是通过引用复制的,它也会改变originalArray [3]。
https://jsfiddle.net/7ajz2m6w/
请注意,array.slice(0)
and array.clone()
会遇到同样的限制。
解决此问题的一种方法是在推送序列中有效地克隆对象:
originalArray.forEach((v, i) => {
const val = (typeof v === 'object') ? Object.assign({}, v) : v;
newArray.push(val);
});
https://jsfiddle.net/e5hmnjp0/
欢呼声
答案 5 :(得分:4)
在JS中,运算符“=”将指针复制到数组的内存区域。 如果要将数组复制到另一个数组,则必须使用克隆函数。
对于整数是不同的,因为它们是原始类型。
S上。
答案 6 :(得分:2)
除了原始数据类型(字符串和数字IIRC)之外,所有内容都通过引用进行复制。
答案 7 :(得分:2)
在arrayCopy中创建原始数组的过滤器。因此,对新阵列的更改不会影响原始阵列。
var myArray = ['a', 'b', 'c'];
var arrayCopy = myArray.filter(function(f){return f;})
arrayCopy.splice(0, 1);
alert(myArray); // alerts ['a','b','c']
alert(arrayCopy); // alerts ['b','c']
希望它有所帮助。
答案 8 :(得分:1)
您没有任何副本 你有多个变量持有相同的数组。
同样,您有多个变量保持相同的数字。
当您编写copyOfMyNumber = ...
时,您将在变量中添加一个新数字
这就像写copyOfMyArray = ...
。
当您编写copyOfMyArray.splice
时,您修改原始数组
数字是不可能的,因为数字是不可变的,不能被修改,
答案 9 :(得分:1)
您可以根据具体情况添加一些错误处理,并使用类似于以下功能的方法来解决问题。请评论任何错误/问题/效率的想法。
function CopyAnArray (ari1) {
var mxx4 = [];
for (var i=0;i<ari1.length;i++) {
var nads2 = [];
for (var j=0;j<ari1[0].length;j++) {
nads2.push(ari1[i][j]);
}
mxx4.push(nads2);
}
return mxx4;
}
答案 10 :(得分:1)
将数组复制到临时变量的另一种方法是将数组类型转换/更改为字符串,然后检索它。
例如
var a = [1,2,3];
typeof(a) (this will give "object")
var b = JSON.stringify(a);
typeof(b) (this will give "string");
b = JSON.parse(b);
typeOf(b) (this will give "object")
现在b的变化不会反映在a
答案 11 :(得分:0)
除非您克隆或复制,否则javascript中的数组或对象始终具有相同的引用。这是一个例子:
http://plnkr.co/edit/Bqvsiddke27w9nLwYhcl?p=preview
// for showing that objects in javascript shares the same reference
var obj = {
"name": "a"
}
var arr = [];
//we push the same object
arr.push(obj);
arr.push(obj);
//if we change the value for one object
arr[0].name = "b";
//the other object also changes
alert(arr[1].name);
对于对象克隆,我们可以在jquery和angular.copy()中使用.clone(),这些函数将使用其他引用创建新对象。如果您知道更多功能,请告诉我,谢谢!
答案 12 :(得分:0)
你的答案就在这里
var myArray = ['a', 'b', 'c'];
var copyOfMyArray = myArray.slice();
基本上,slice()操作克隆数组并返回浅表副本。
copyOfMyArray.splice(0, 1);
alert(myArray); // alerts ['a', 'b', 'c']
alert(copyOfMyArray); // alerts ['b','c']
可在以下链接中找到明确的文档: Array.prototype.slice()
答案 13 :(得分:0)
var myArray = ['a', 'b', 'c'];
var copyOfMyArray = JSON.parse(JSON.stringify(myArray));
copyOfMyArray.splice(0,1);
console.log('orginal Array',myArray)
console.log('After Splic of copyOfMyArray',copyOfMyArray);
//If not using the JSON.parse(JSON.stringify (array)) at the time of assign the array change of the one array will affect another because of the reference.
答案 14 :(得分:0)
浅表复制的问题是不是所有对象都被克隆,而是被引用,所以array.slice(0)仅适用于文字数组,而不能进行浅表复制。在这种情况下,一种方法是..
var firstArray = [{name: 'foo', id: 121}, {name: 'zoo', id: 321}];
var clonedArray = firstArray.map((_arrayElement) => Object.assign({}, _arrayElement));
console.log(clonedArray);
// [{name: 'foo', id: 121}, {name: 'zoo', id: 321}] // shallow copy
答案 15 :(得分:0)
如果您有jQuery
const addItem = item => ({type: 'ADD_ITEM', item})
const removeFirstItem = () => ({type: 'REMOVE_FIRST_ITEM'})
const fifoReducer = (prev = defaultValue, action = {}) => {
const { type, item} = action;
switch (type) {
case "ADD_ITEM":
return [...prev, item];
case "REMOVE_FIRST_ITEM":
return prev.slice(1);
default: {
return prev;
}
}
};
是一种无需引用即可复制嵌套对象的方法。