我不明白为什么会发生这种情况。让我们说我定义一个对象并创建一个3对象的数组。如果我修改数组中的对象,它会影响对象的所有实例吗?有人可以解释为什么会这样吗?另外,如何使用对象的独立“Copies”创建一个数组以获得所需的行为?谢谢!
例如
library(data.table)
#Set random seed
set.seed(2017)
#Create a table with the attributes we need
x = data.table(rbind(data.frame(Field1 = 1:12,Field2 = rep(1:3, each = 4), Value = runif(12)),
data.frame(Field1 = 1:12,Field2 = rep(1:3, each = 4), Value = runif(12))))
#Let's order by Field2/ Field1 / Value
x = x[order(Field2,Field1,Value)]
#Check
print(x)
# This works, but requires 2 steps which can complicate things when needing
# to pull other attributes too.
(x[,.(Value = sum(Value)),.(Field2,Field1)][,.SD[which.max(Value)],.(Field2)])
#This instead provides the row corresponding to the largest Value.
(x[,.(Field1 = Field1[which.max(Value)]),.(Field2)])
# This is what I was ideally looking for but it only returns the first row of the attribute
# regardless of the value of Value, or the corresponding sum.
(x[,.(Field1 = Field1[which.max(sum(Value))]),.(Field2)])
# This works but seems clumsy
(x[,
.SD[, .(RKCNT=length(.I),TotalValue=sum(Value)), .(Field1)]
[,.(RKCNT = sum(RKCNT), TotalValue = sum(TotalValue),
Field1 = Field1[which.max(TotalValue)])],
.(Field2)])
答案 0 :(得分:2)
与基元(字符串,数字,布尔值,符号null,未定义)相反,javascript中的对象由reference
传递。变量用作这些对象的占位符/指针。要创建没有变异风险的对象副本,您可以使用spread(禁止兼容性):
const newObject = { ...testObject };
或传统上, Object.assign() ,传递空对象文字以避免原始testObject
的可变性:
const newObject = Object.assign({}, testObject);
就深度克隆而言,MDN建议使用JSON.parse()
和JSON.stringify()
的组合。例如:
const testObject = { value: "a", other: { value2: b } };
const newObject = JSON.parse(JSON.stringify(testObject));
答案 1 :(得分:0)
您正在循环中反复推送相同对象的引用。
for(i=0; i < 3; i++){
var newobj = testObject; //no new object,same object's reference again
objArray.push(newobj); //push new object to array
}
应该是
for(i=0; i < 3; i++){
var newobj = {"value1":"a","value2":"b"}; //make a new testObject
objArray.push(newobj); //push new object to array
}
答案 2 :(得分:0)
在JavaScript中创建对象时,实际上是在为该对象创建引用。您可以将其存储在变量中并传递它...也许将其附加到数组中。当您对对象引用进行操作时,它会找到引用指向并更新它的原始对象。因此,当您使用.push
时,它不会创建新对象,而只是将引用推送到该对象。如果您在一个位置更新它,它将在另一个以及您已分配该引用的任何其他位置更新它。
将对象复制到新对象通常称为 cloning 。在JavaScript中克隆对象有很多不同的方法,结果各不相同。
您可以使用var newobj = { ...testObject }
作为另一个答案建议。此扩展运算符基本上复制testObject
的属性并创建一个新对象(使用外部{
}
声明)。然后将对 new 对象的引用分配给newobj
。您可以将其视为:
var newobj = {
value1: testObject.value1,
value2: testObject.value2,
};
然而,你应该记住,这只给你一个级别的克隆。也就是说,如果您的对象包含其他对象,则该对象的引用将被指定为属性而不是该对象的克隆。例如:假设你有:
var testObject = { obj: { a: "b" } };
var newobj = { ...testObject };
delete testObject.obj.a;
console.log(newobj); // { obj: {} }
为了解决这个问题,您需要执行所谓的深度克隆,在JavaScript中可以通过递归克隆同时也是对象的对象属性来完成。有很多方法可以做到这一点,包括lodash
等库或本土函数。关于SO的一个例子:What is the most efficient way to deep clone an object in JavaScript?
最后,如果testObject
应该是对象模板或其他newobj
派生的初始状态,那么使用函数可能更有意义:
function newObjFactory() {
return {
value1: "a",
value2: "b",
};
}
然后你可以做var newobj = newObjFactory()
每次你得到一个新对象,因为每次调用和return
编辑时,函数都会创建一个新对象。