4

我是 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
4

3 回答 3

2

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)

这将创建全新的副本。 在此处输入图像描述

于 2018-10-23T05:35:11.540 回答
1

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

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

从子对象读取属性:

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

在子对象中写入属性

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

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


bar.details.version = 2.2;

 What Javascript parser does:
  1. 首先,通过原型链搜索来定位细节,它会在foo上找到(即:bar.details === foo.details

  2. 其次,版本直接设置在详细信息对象上(这就是为什么this.details.versionthis.details.name都“意外”更改,正如您在结果中看到的那样,结果bar.details.version === foo.details .version === 2.2 ))


bar.a = 123456;

What Javascript parser does:

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

于 2018-10-23T06:23:39.883 回答
-1

create 方法正在执行浅拷贝。

--编辑--

不,看起来可能是这样,但术语浅拷贝是不准确的。它会更符合原型继承 MDN文章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

希望这可以帮助。干杯,

于 2018-10-23T05:48:08.143 回答