是Object.create()方法执行浅表复制吗?

时间:2018-10-23 05:28:15

标签: javascript scratchpad

我是JavaScript的新手。当我阅读Object.create文档时,其编写方式类似于“ Object.create()方法使用现有对象创建新对象”(参考: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

3 个答案:

答案 0 :(得分:1)

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

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

从子对象读取属性:

当您尝试从子对象访问属性时,Javascript解析器将尝试遍历整个原型链,直到设法找到它为止;否则,如果未找到,则返回undefined。

在子对象中写入属性

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

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


bar.details.version = 2.2;

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

  2. 第二,版本直接在 details 对象上设置(这就是 this.details.version this的原因。正如您在结果中看到的那样,details.name 都被“意外地”更改,结果 bar.details.version === foo.details.version === 2.2 )))< / p>


bar.a = 123456;

What Javascript parser does:

开始任何操作之前,已经找到了,并且无需搜索原型链,因此, a 直接设置在上 (即,这就是为什么只有bar.a会受 foo.a 保持原值的影响: 123456

答案 1 :(得分:0)

Object.Create完全不复制任何内容,它只是设置 传递的对象作为新对象的原型:

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

console.log(newPerson)

enter image description here

要进行浅表复制,可以使用Object.assign

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

这将创建全新的副本。 enter image description here

答案 2 :(得分:-1)

  

create方法正在执行浅表复制。

-编辑-

不,看起来好像是这样,但是术语浅拷贝可能不准确。这将更符合原型继承 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

希望这会有所帮助。干杯,