昨天写了一篇关于 Spread Operator 应用在 Object 上的博文,但是最后举例 Object.assign()
与 ...
区别时,有些混淆,今天查了些资料,作为总结。
...
和 Object.assign()
整体的用法非常下关系,主要区别在于 Object.assign()
函数会触发 setters,而 ...
语法则不会,也就是说 ...
是定义了新属性,而 Object.assign()
则是设置了它们。
Object.assign()
的基本用法
-
改变原有对象
Object.assign(target, source1, source2); 复制代码
target
已经被修改,source1
以及source2
会被复制到其中。 -
创建新的对象
const result = Object.assign({}, source1, source2); 复制代码
result
是一个新的对象,source1
以及source2
被复制到其中。
在第二种方法上,...
与 Object.assign()
是非常类似的。接下来,阐述它们之间具体的相似点和不同点。
Object.assign
与 ...
的相同点
-
...
和Object.assign()
都是通过get
运算符来取值在将它们写入目标之前,这两个操作都会使用
get
操作从源对象读取相应的属性值。因此,在此过程中,getter
将转换为正常的数据属性,具体如下const original = { get foo() { console.log('getter'); return 123; } }; 复制代码
original
对象有getter foo
,而setter
为undeined
Object.getOwnPropertyDescriptor(original, 'foo') /* log { get: [Function: foo], set: undefined, enumerable: true, configurable: true } */ 复制代码
但是,利用
Object.assgin()
以及...
对original
对象进行克隆时,会发现const clone1 = {...original}; // 触发 original 的 getter 会 log "getter" Object.getOwnPropertyDescriptor(clone1, 'foo'); /* log getter 以及被转换为正常的数据属性 { value: 123, writable: true, enumerable: true, configurable: true } */ const clone2 = Object.assign({}, original); // 触发 original 的 getter 会 log "getter" Object.getOwnPropertyDescriptor(clone2, 'foo') { value: 123, writable: true, enumerable: true, configurable: true } 复制代码
上述结果表明,在得到的
clone1
和clone2
中,foo
只是一个普通的数据属性(它的属性描述符具有属性值和可写); -
...
和Object.assign
只会处理可枚举数据这两个操作都会忽略所有继承的属性和所有不可枚举的属性。
const proto = { inheritedEnumerable: 1, }; const obj = Object.create(proto, { ownEnumerable: { value: 2, enumerable: true, }, ownNonEnumerable: { value: 3, enumerable: false, }, }); console.log(obj); // { ownEnumerable: 2, ownNonEnumerable: 3, __proto__: { inheritedEnumerable: 1 } } console.log({ ...obj }); // { ownEnumerable: 2 } console.log(Object.assign({}, obj)); // { ownEnumerable: 2 } 复制代码
Object.assign
与 ...
的不同点
它们的不同点在于 ...
会定义属性,而 Object.assign()
会设置它们,也就是说 ...
定义了目标对象中的新属性,Object.assign()
则是使用 set
操作符进行写入。
Object.defineProperty(Object.prototype, 'foo', {
set(value) {
console.log('SET', value);
},
});
const obj = {foo: 123};
console.log(Object.assign({}, obj));
// 会触发 set, log SET 123
// log {}
console.log({ ...obj });
// log { foo: 123 }
复制代码