Javascript 为什么局部数组的推送会改变全局数组?
我不明白为什么下面这段代码将同时返回本地数组和全局数组的突变:Javascript 为什么局部数组的推送会改变全局数组?,javascript,Javascript,我不明白为什么下面这段代码将同时返回本地数组和全局数组的突变: var globalarray = [1,2,3]; function test(){ let localarray = globalarray; localarray.push(4); console.log(localarray); console.log(globalarray); } setInterval(test, 2000); 返回: [1,2,3,4] for bo
var globalarray = [1,2,3];
function test(){
let localarray = globalarray;
localarray.push(4);
console.log(localarray);
console.log(globalarray);
}
setInterval(test, 2000);
返回:
[1,2,3,4] for both
我的印象是localarray将是globalarray的副本。我看到的另一个答案是,为了制作数组的副本,您需要使用.slice.reverse,这似乎是一个解决方法。为什么它不只是创建一个新的本地副本?是否有一种简单有效的方法来制作全局数组的本地副本?否则,对一个全局数组进行多次变异似乎会对性能造成严重影响。在JavaScript和许多其他语言中一样,对象是通过引用传递的。数组也是通过引用传递的,因为数组实际上是一种对象类型。因此,当您说:让localarray=globalarray时,实际上是将localarray设置为解析为globalarray的指针 获得真实副本有几种策略。如果您试图获取原始数组的新副本,则.map的数组原型函数是该任务最有针对性的工具之一。它看起来是这样的:
let localarray = globalarray.map(element => element);
与许多其他语言一样,在JavaScript中,对象是通过引用传递的。数组也是通过引用传递的,因为数组实际上是一种对象类型。因此,当您说:让localarray=globalarray时,实际上是将localarray设置为解析为globalarray的指针 获得真实副本有几种策略。如果您试图获取原始数组的新副本,则.map的数组原型函数是该任务最有针对性的工具之一。它看起来是这样的:
let localarray = globalarray.map(element => element);
代码中出现这种情况的原因是,您只是告诉测试函数使用=运算符指向globalarray。这是因为在JavaScript中,变量赋值不会将对象固有地复制到新变量中;这似乎令人困惑,因此只需将=运算符视为将代码指向对象位置的符号即可 =操作员制作新副本的唯一时间是在您使用时。在这些情况下,您无法从本质上更改这些对象是什么,因此=就足以生成您所期望的副本 之所以使用.slice.reverse,是为了解决您看到的问题。另一种方法是使用let localarray=globalarray.mape=>e,或者按照samee的建议,使用let localarray=[…globalarray]。.map运算符将给定给它的函数作为第一个参数,并将其应用于每个元素,然后将结果存储在与globalarray不同的另一个位置的不同数组中 请记住,这些方法,以及可能向您建议的任何其他方法,都是速记方法
let localarray = new Array(globalarray.length);
for (let i = 0; i < globalarray.length; i++) {
localarray[i] = globalarray[i];
}
// localarray can now be freely modified because it does not point to the same array as globalarray
还要记住,如果还需要在数组内部创建元素的副本,则必须使用更全面的复制代码。如果您确实需要,有些库可以执行这种重载复制。代码中出现这种情况的原因是,您只是告诉测试函数使用=运算符指向globalarray。这是因为在JavaScript中,变量赋值不会将对象固有地复制到新变量中;这似乎令人困惑,因此只需将=运算符视为将代码指向对象位置的符号即可 =操作员制作新副本的唯一时间是在您使用时。在这些情况下,您无法从本质上更改这些对象是什么,因此=就足以生成您所期望的副本 之所以使用.slice.reverse,是为了解决您看到的问题。另一种方法是使用let localarray=globalarray.mape=>e,或者按照samee的建议,使用let localarray=[…globalarray]。.map运算符将给定给它的函数作为第一个参数,并将其应用于每个元素,然后将结果存储在与globalarray不同的另一个位置的不同数组中 请记住,这些方法,以及可能向您建议的任何其他方法,都是速记方法
let localarray = new Array(globalarray.length);
for (let i = 0; i < globalarray.length; i++) {
localarray[i] = globalarray[i];
}
// localarray can now be freely modified because it does not point to the same array as globalarray
还要记住,如果还需要在数组内部创建元素的副本,则必须使用更全面的复制代码。如果您真的需要,有些库可以执行这种重载复制。克隆阵列的简单方法就是
let localarray = globalarray.slice();
我用另一种方式进行深度克隆:
clone: function() {
var clone = undefined;
var instance = this;
if ( XScript.is.xobject(instance) ) {
clone = {};
for ( var prop in instance ) {
if ( instance.hasOwnProperty(prop) ) {
var p = instance[prop];
if ( XScript.is.xobject(p) ) p = p.clone();
clone[prop] = p;
}//END IF this
}//END FOR prop
return clone;
}//END IF xobject
if ( XScript.is.xarray(instance) ) {
clone = instance.slice(0);
return clone;
}
return clone;
}//END FUNCTION clone
此克隆将要求您将克隆对象附加到对象原型,并检查其是否为数组、对象或其他对象。我不会改变功能来满足你的所有需求,因为你应该学会如何改变它,以及如何做,而不是复制意大利面。另外,这只是一个例子。克隆阵列的简单方法就是
let localarray = globalarray.slice();
我用另一种方式进行深度克隆:
clone: function() {
var clone = undefined;
var instance = this;
if ( XScript.is.xobject(instance) ) {
clone = {};
for ( var prop in instance ) {
if ( instance.hasOwnProperty(prop) ) {
var p = instance[prop];
if ( XScript.is.xobject(p) ) p = p.clone();
clone[prop] = p;
}//END IF this
}//END FOR prop
return clone;
}//END IF xobject
if ( XScript.is.xarray(instance) ) {
clone = instance.slice(0);
return clone;
}
return clone;
}//END FUNCTION clone
此克隆将要求您附加克隆
对象,并检查其是否为数组、对象或其他。我不会改变功能来满足你的所有需求,因为你应该学会如何改变它,以及如何做,而不是复制意大利面。另外,这只是一个例子。赋值运算符只需将现有数组的引用赋值给新变量即可。让localarray=globalarray不会创建新数组并分配给globalarray。您可以使用spread运算符让localarray=[…globalarray],但请记住spread运算符只进行浅层复制。赋值运算符的可能重复项只是将现有数组的引用赋值给新变量。让localarray=globalarray不会创建新数组并分配给globalarray。您可以使用spread运算符让localarray=[…globalarray],但请记住spread运算符只进行浅层复制