我很困惑为什么以下这段代码将返回局部数组和全局数组的突变:
public partial class MainPage : ContentPage
{
public ObservableCollection<IDevice> Devices { get; set; }
public MainPage()
{
Devices = new ObservableCollection<IDevice>();
Padding = new Thickness(0, 20, 0, 0);
var listView = new ListView();
listView.ItemsSource = Devices;
Content = listView;
Refreshcmd();
}
public void Refreshcmd()
{
var adapter = CrossBluetoothLE.Current.Adapter;
adapter.DeviceDiscovered += (s, a) => Devices.Add(a.Device);
adapter.StartScanningForDevicesAsync();
}
}
返回:
Devices
我的印象是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
,这似乎是一种解决方法。为什么不仅创建新的本地副本?有没有简单有效的方法来创建全局数组的本地副本?否则,对全局数组进行多次更改似乎会降低性能。
答案 0 :(得分:1)
在JavaScript(与许多其他语言一样)中,对象是通过引用传递的。数组也通过引用传递(因为数组实际上是对象的一种类型)。因此,当您说:let localarrray = globalarray
时,实际上是将localarray
设置为解析为globalarray
的指针。
有几种获取真实副本的策略。如果您要获取原始数组的新副本,则.map()
的Array prototype函数是最有针对性的工具之一。看起来像这样:
let localarray = globalarray.map(element => element);
答案 1 :(得分:1)
在代码中这样做的原因是因为您只是在使用test
运算符告诉您的globalarray
函数指向=
。这是因为在JavaScript中,变量分配并不会固有地将对象“复制”到新变量中;这似乎令人困惑,所以只需将=
运算符视为将代码指向对象位置的符号。
=
操作员制作新副本的唯一次数是在使用primitive types时。在这些情况下,您无法固有地更改这些对象的含义,因此=
足以像您期望的那样进行复制。
使用.slice().reverse()
的原因是要解决您遇到的问题。您可以执行此操作的另一种方法是使用let localarray = globalarray.map(e => e)
,或者如建议的一样,使用let localarray = [...globalarray]
。 .map
运算符将赋予它的函数作为第一个参数,并将其应用于每个元素,然后将结果存储在与另一个不同的 different 数组中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
还请记住,如果您还需要在数组内部创建元素的副本,那么您将必须使用更全面的复制代码。如果您确实需要,有些库可以执行这种繁重的复制。
答案 2 :(得分:1)
克隆数组的简单方法就是
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
此克隆将要求您将克隆对象附加到对象原型,并检查其是否为数组,对象或其他。我不会根据您的所有需求更改此功能,因为您应该学会一些如何更改它以及如何操作的方法,而不是复制面食。另外,这只是一个例子。