在JavaScript中,对象的assign方法将源对象自己的可枚举属性复制到目标对象,并返回该目标对象。
上面的句子中有两个重要的关键词:
- 可枚举
- 自己的
在我们继续理解Object.assign的目的之前,我们必须真正理解这两个词,可枚举属性和自己的属性。让我们逐一看看:
JavaScript对象可以具有可枚举或不可枚举的属性。但是,默认情况下,当您在对象上创建属性时,它是可枚举的。可枚举意味着您可以枚举这些属性。让我们通过代码来理解它。
const babycat = { 年龄: '1',颜色: '白色' } 对于 (babycat中的var prop) {console.log(prop);}
babycat对象中有两个属性。默认情况下,两者都是可枚举的,因此作为for .. in循环的输出,您将获得年龄和名称打印。
现在让我们使用object.Defineproperty方法更改age属性的默认可枚举行为。
const babycat = { 年龄: '1',颜色: “ 白色” } Object.de fineProperty(babycat, 'age', { enumerable: false }); 对于 (babycat中的var prop) {console.log(prop);}
我们已将年龄属性的enumerable更改为false,因此作为输出,您将只获得彩色打印。因此,年龄不再是babycat对象的可枚举属性。
上面句子中的另一个关键字是自己的属性要理解它,你需要了解对象原型链。所有JavaScript对象都是原型链的一部分,因此也可以访问其原型的属性。因此,自己的属性是那些特定于对象而不是来自原型链的属性。让我们通过代码示例了解自己的属性,
const cat = {名称: 'foo'} const babycat = {年龄: '1',颜色: “ 白色”} // babycat.__Proto __ = cat; // 我更喜欢这个对象。setPrototypeOf(babycat,cat); 对于 (babycat中的var prop) {console.log(prop);}
在上面的代码片段中,有两个对象cat和babycat。此外,babycat对象的 [[Prototype]] 属性设置为cat对象。当您使用for .. in循环打印babycat对象的属性时,您将发现作为输出年龄,颜色,名称打印如下图所示:
这里发生了什么?JavaScript打印原型链中的所有属性。但是,只有年龄和颜色是babycat对象的属性。到目前为止,您应该已经在JavaScript对象的上下文中了解自己的属性和可枚举属性。所以让我们重温这篇文章的第一句话,
在JavaScript中,Object的assign方法将源对象自己的可枚举属性复制到目标对象,并返回该目标对象。你应该能够推断出上面的句子到底意味着什么。考虑下面的代码:
const cat = { 名称: 'foo'} const babycat = Object.assign({}, cat); 对于 (babycat中的var prop) {console.log(prop ':' babycat[prop]);}
使用Object.assign() 方法,我们将cat对象自己的可枚举属性复制到babycat对象。在这里,猫对象是源和babycat对象是目标。您将获得打印如下的输出:
Object.assign() 方法在源对象上使用 [[Get]],在目标对象上使用 [[set]],并调用setter和getter来执行任务。本质上,它将属性值从源分配到目标对象。它不会在目标对象中创建新属性。到目前为止,您已经知道Object.assign() 方法的用途。让我们在将属性从源对象复制到目标对象时检查一些变化。
相同的属性在这两个目标和源对象
如果目标对象具有与源对象相同的属性,则object.assign() 方法将覆盖目标对象属性。要理解它,请考虑下面的代码清单:
const cat = { 名称: 'foo'年龄: 9} const babycat = Object.assign({ age: 1 }, cat); 对于 (babycat中的var prop) {console.log(prop ':' babycat[prop]);}
目标对象和源对象中都有age属性。在目标对象中复制属性时,object.assign() 方法将覆盖目标对象age属性,因此您将获得如下图所示的输出:
深度克隆对象
正如我们在之前的例子中看到的,使用Object.assign() 方法可以执行克隆。要刷新,请在下面的代码片段执行克隆。
const cat = { 名称: 'foo'年龄: 9} const babycat = Object.assign({}, cat); 对于 (babycat中的var prop) {console.log(prop ':' babycat[prop]);}
Object.assign() 复制值。因此,如果源对象具有引用类型,它将复制引用值。让我们通过代码来理解它:
const cat = { 名称: 'foo'年龄: 9岁,孩子: {nochild: 2}} const babycat = Object.assign({}, cat); console.lo g(cat.name); // foo控制台.lo g(babycat.name); // fooconsole.log(cat.child.nochild); // 2console.log(babycat.child.nochild); // 2babycat.name = 'koo'babycat.child.nochild = 9; console.lo g(cat.name); // fooconsole.lo g(babycat.name); // kooconsole.log(cat.child.nochild); // 9console.log(babycat.child.nochild); // 9
在上面的例子中,Object.assign将复制
- 姓名和年龄
- 子级的引用的值,因为它是引用类型。
由于仅复制for name属性的值,因此当您在babycat对象中更改其值时,它不会影响cat对象的name属性。但是,当您更改babycat对象上的子属性的值时,它也会更改cat对象的值,因为它的引用类型性质。正如预期的那样,当你运行上面的样本,你会得到输出如下图所示:
合并多个源对象
使用Object.assign() 方法,您还可以将多个对象合并到目标对象。考虑下面列出的代码:
const obj1 = { a: 1} const obj2 = { b: 2} const obj3 = { c: 3} const obj4 = Object.assign({}, obj1, obj2, obj3, { d: 4 });对于 (让obj4中的p) {console.log(obj4[p]);}
我们正在将obj1,obj2,obj3和未命名对象合并到目标对象obj4。您将获得打印如下的输出:
Null和Undefined
JavaScript Object.assign() 方法在复制对象时忽略null和undefined。考虑下面列出的代码:
const obj1 = { a: 1} const obj2 = Object.assign({}, obj1, null, undefined, { d: 4 });对于 (让obj2中的p) {console.log(obj2[p]);}
作为输出,您将获得1和4打印,因为assign方法忽略undefined和null。
您应该使用JavaScript Object.assign() 方法将源对象自己的可枚举属性复制到目标对象。它通过从源对象复制值来克隆对象。</p