gpt4 book ai didi

javascript - 从 Object.create() 方法返回的新对象似乎覆盖了它的原始对象,这不是我所期望的

转载 作者:行者123 更新时间:2023-11-29 23:16:36 24 4
gpt4 key购买 nike

我是 JavaScript 世界的新手。我希望 Object.create(foo) 方法创建一个“foo”类型的新对象。但是,如下例所示,新创建的对象似乎有一些成员属性仍然引用其原始对象的属性。因此,如果修改了新值,新值将覆盖原始值。

我知道 JavaScript 使用“按引用复制”,除了复制原语。但是,正如许多 JavaScript 指南/引用所说,每次调用 Object.create(foo) 都会创建一个新的“foo”对象,不是吗?

说到我的例子,

"using strict";
var A = {a:1, b:1, c:1};
var B = Object.create(A);

console.log("// STEP 1 ////////////////////");
B.a = 2; B.b = 2; B.c = 2;
console.log(A); // Object { a: 1, b: 1, c: 1 }
console.log(B); // Object { a: 2, b: 2, c: 2 }

console.log("// STEP 2 ////////////////////");
var AA = {
_a: Object.create(A),
_b: Object.create(B)
}
console.log("AA.a = " + AA._a.a + " : " + AA._a.b + " : " + AA._a.c); // AA.a = 1 : 1 : 1
console.log("AA.b = " + AA._b.a + " : " + AA._b.b + " : " + AA._b.c); // AA.b = 2 : 2 : 2

console.log("// STEP 3 ////////////////////");
var BB = Object.create(AA);
console.log("AA.a = " + AA._a.a + " : " + AA._a.b + " : " + AA._a.c); // AA.a = 1 : 1 : 1
console.log("AA.b = " + AA._b.a + " : " + AA._b.b + " : " + AA._b.c); // AA.b = 2 : 2 : 2
console.log("BB.a = " + BB._a.a + " : " + BB._a.b + " : " + BB._a.c); // BB.a = 1 : 1 : 1
console.log("BB.b = " + BB._b.a + " : " + BB._b.b + " : " + BB._b.c); // BB.b = 2 : 2 : 2

console.log("// STEP 4 ////////////////////");
BB._a.a = 3, BB._a.b = 3, BB._a.c = 3;
console.log("AA.a = " + AA._a.a + " : " + AA._a.b + " : " + AA._a.c); // AA.a = 3 : 3 : 3
console.log("AA.b = " + AA._b.a + " : " + AA._b.b + " : " + AA._b.c); // AA.b = 2 : 2 : 2
console.log("BB.a = " + BB._a.a + " : " + BB._a.b + " : " + BB._a.c); // BB.a = 3 : 3 : 3
console.log("BB.b = " + BB._b.a + " : " + BB._b.b + " : " + BB._b.c); // BB.b = 2 : 2 : 2

在第 3 步之前,我已经预料到并理解了输出。但是,我在第 4 步遇到了麻烦。为什么对象 BB 在这里覆盖了 AA 的成员属性(_a.a、_a.b 和 _a.c)?现在,我真的对 Object.create() 方法的行为感到困惑。

我的目标是第 4 步的以下输出:

BB._a.a = 3, BB._a.b = 3, BB._a.c = 3;
console.log("AA.a = " + AA._a.a + " : " + AA._a.b + " : " + AA._a.c); // AA.a = 1 : 1 : 1
console.log("AA.b = " + AA._b.a + " : " + AA._b.b + " : " + AA._b.c); // AA.b = 2 : 2 : 2
console.log("BB.a = " + BB._a.a + " : " + BB._a.b + " : " + BB._a.c); // BB.a = 3 : 3 : 3
console.log("BB.b = " + BB._b.a + " : " + BB._b.b + " : " + BB._b.c); // BB.b = 2 : 2 : 2

只有我怀疑的地方是步骤 2 中成员 _a 和 _b 的声明。Object.create(A) 和 Object.create(B) 的使用可能是问题的原因。但我无法说服自己或改善这种情况。

我在这里错过了什么?我应该如何更正代码以获得我的瞄准结果?

---------------- 我的补充评论从这里开始----------------

在收到@Mark Meyer 的回放后(感谢!),我了解了 Object.create() 方法的概念。但是,那么,我们如何以通用的对象编程风格实现一个包含其他类的类呢?例如:

var CPU = { name: null };
var MB = { name: null };
var PC = { cpu: Object.create(CPU), mb: Object.create(MB) };

var pc1 = Object.create(PC);
pc1.cpu.name = "Intel i7";
pc1.mb.name = "ASUS";

var pc2 = Object.create(PC);
pc2.cpu.name = "AMD ryzen",
pc2.mb.name = "GIGABYTE";

console.log("PC1 has CPU: " + pc1.cpu.name + " MB: " + pc1.mb.name); // PC1 has CPU: AMD ryzen MB: GIGABYTE
console.log("PC2 has CPU: " + pc2.cpu.name + " MB: " + pc2.mb.name); // PC2 has CPU: AMD ryzen MB: GIGABYTE

我现在知道为什么 pc2 会在这里覆盖 pc1。我希望 pc1 和 pc2 独立运行。但是,我无法想出另一种方法来实现我的目标。有什么办法可以避免这种情况吗?

最佳答案

A = Object.create(B) 创建一个新对象A原型(prototype)链接B。它不会将属性复制A。这意味着 A 能够访问 B 上的属性,如果它本身没有这些属性的话。当 A 没有某些属性时,它会查看 B 是否有并使用它。例如:

let A = {a:1, b:1, c:1};
let B = Object.create(A)

console.log("does B have an 'a' prop?", B.hasOwnProperty('a'))
console.log("does A have an 'a' prop?", A.hasOwnProperty('a'))

console.log(B.a) // accesses A.a because there is no B.a
A.a = 10 // changing A.a
console.log(B.a) // is reflected here

当您向 B 添加属性时,它现在拥有自己的属性,不再需要延迟原型(prototype)链:

let A = {a:1, b:1, c:1};
let B = Object.create(A)
B.a = "hello"

console.log("does B have an 'a' prop?", B.hasOwnProperty('a'))
console.log("does A have an 'a' prop?", A.hasOwnProperty('a'))

console.log(B.a) // B now has it's own a property
A.a = 10 // so changing A.a
console.log(B.a) // doesn't change this

当属性指向其他对象时,请记住同样的道理。除非 B 有它自己的对象版本,否则当 B 访问该对象时,将看到对 A 上对象的更改。由于 BA 指向相同的引用,因此 B 也可以对对象进行更改,您将在您查看 A 对对象的引用:

let A = {a:{test: "Object A.a"}};
let B = Object.create(A)

console.log("A.a and B.a are the same object?", A.a === B.a)

console.log(B.a) // B.a still points to A.a
A.a.test = "A changed"
console.log(B.a) // B.a still points to A.a so it sees the change

B.a.test = "B changed me" // this doens't create an `a` property on B
// B.a and A.a still point to the same object

console.log(A.a) // B changed the test prop on this object

// give B it's own a property:
B.a = {test: "B's own"}
console.log("A.a and B.a are the still same object?", A.a === B.a)

关于javascript - 从 Object.create() 方法返回的新对象似乎覆盖了它的原始对象,这不是我所期望的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52528193/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com