Object.create() 方法执行浅拷贝?

is Object.create() method performs shallow copy?

我是 JavaScript 的新手。当我阅读 Object.create 文档时,它写成 'The Object.create() method creates a new object, using an existing object'(参考:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create)。它没有提及有关对象的浅拷贝的任何内容。但是当我试验下面的脚本时,我确认,create 方法正在执行浅拷贝。

var foo = {
  a : 100,
  details : {
    version : 1.1,
    name : 'Demo of object inheritance'
  },

  printInfo : function(){
    console.log(this.details.version);
    console.log(this.details.name);
    console.log(this.a);
  }

}

var bar = Object.create(foo);

foo.printInfo();
bar.printInfo();

console.log("\n Updating the details and property a of bar object");

bar.details.version = 2.2;
bar.details.name = "Bar object changed the name";
bar.a = 123456;

console.log("\n")
foo.printInfo();
bar.printInfo();

我的理解对吗?请指出任何确认 create() 方法执行浅拷贝的文档。

当我在 Scratchpad 中执行时,我在控制台中看到以下输出。

1.1
Demo of object inheritance
100
1.1
Demo of object inheritance
100

Updating the details and property a of bar object Scratchpad/1:21:1


2.2
Bar object changed the name
100
2.2
Bar object changed the name
123456

Object.Create 根本不复制任何东西,它只是设置 传递的对象作为新对象的原型:

const person = {name: 'Alex', age: 29}
const newPerson = Object.create(person)

console.log(newPerson)

为了进行浅拷贝,可以使用Object.assign

const newPersonObj = Object.assign({}, person)
console.log(newPersonObj)

这将创建全新的副本。

create method is performing shallow copy.

-- 编辑 --

不,它可能看起来是这样,但术语 浅拷贝 是不准确的。这样会更符合原型继承 MDN article here

给定一个对象 oA,它有一个 name 属性,函数 Object.create(oA) 创建一个新对象 oB。尝试访问 属性 oB.name 会查找原型链,直到它在 oA.name.

的原型上找到一个

示例代码如下:

/* create one object adam */
const adam = {
 name: 'Adam',
} 
console.log(`does adam have own 'name' property?`, adam.hasOwnProperty('name')) // true

/* create new object bob, whose prototype 'ancestor' is adam */
const bob = Object.create(adam)
console.log(`does bob have own 'name' property? (1)`, bob.hasOwnProperty('name')) // false; the 'name' prop is on adam

/* assigning 'name' on bob doesn't change adam's name, it just 'shadows' it -- accessing 'name' on bob returns the one on bob */
bob.name = 'Bob'
console.log(`does bob have own 'name' property? (2)`, bob.hasOwnProperty('name')) // now true

/* adam and bob now each have their own 'name' property */
console.log(adam.name) // Adam
console.log(bob.name)  // Bob

/* show the relationship of adam and bob */
console.log(`is adam a prototype 'ancestor' of bob?`, adam.isPrototypeOf(bob)) // true, linked via Object.create()
console.log(`is bob a prototype 'ancestor' of adam?`, bob.isPrototypeOf(adam)) // false, the prototype points one way

希望这对您有所帮助。干杯,

与浅拷贝无关。 相反,您已经弄清楚 原型继承 在 Javascript 世界中是如何工作的。

为了更好地理解,让我们将其分为以下两部分:

正在从子对象读取 属性:

当您尝试从子对象访问 属性 时,Javascript 解析器将尝试向上搜索原型链,直到设法找到它,否则 return undefined if not找到了。

在子对象中写入属性

它将首先尝试定位您的目标 属性 所属的对象,然后直接在该对象上设置 属性。

让我们以您的部分代码为例:


bar.details.version = 2.2;

 What Javascript parser does:
  1. 首先通过原型链搜索找到详情,在foo(即:bar.details === foo.details

  2. 其次,version直接设置在details对象上(所以this.details.versionthis.details.name 都已 "unexpectedly" 更改,正如您在结果中看到的那样 bar.details.version === foo.details.version === 2.2))


bar.a = 123456;

What Javascript parser does:

在任何事情开始之前,bar 已经定位,不需要搜索原型链,因此,a直接 设置在 bar (即,这就是为什么只有 bar.a 受到 foo.a 仍然保持原始值的影响:123456