Object.assign()
Object.assign()
静态方法将所有 enumerable own properties 从一个或多个源对象复制到目标对象。它返回修改后的目标对象。
¥The Object.assign()
static method
copies all enumerable
own properties from one or more
source objects to a target object. It returns the modified target
object.
Try it
语法
参数
返回值
描述
¥Description
如果目标对象中的属性具有相同的 key,则源对象中的属性将覆盖它们。后来的来源的属性会覆盖早期的属性。
¥Properties in the target object are overwritten by properties in the sources if they have the same key. Later sources' properties overwrite earlier ones.
Object.assign()
方法仅将可枚举属性和自己的属性从源对象复制到目标对象。它在源上使用 [[Get]]
,在目标上使用 [[Set]]
,因此它将调用 getters 和 setters。因此,它分配属性,而不是复制或定义新属性。如果合并源包含 getter,这可能会使其不适合将新属性合并到原型中。
¥The Object.assign()
method only copies enumerable and
own properties from a source object to a target object. It uses
[[Get]]
on the source and [[Set]]
on the target, so it will
invoke getters and setters. Therefore it
assigns properties, versus copying or defining new properties. This may make it
unsuitable for merging new properties into a prototype if the merge sources contain
getters.
要将属性定义(包括其可枚举性)复制到原型中,请改用 Object.getOwnPropertyDescriptor()
和 Object.defineProperty()
。
¥For copying property definitions (including their enumerability) into prototypes, use
Object.getOwnPropertyDescriptor()
and
Object.defineProperty()
instead.
¥Both String
and Symbol
properties are copied.
如果发生错误,例如,如果属性不可写,则会引发 TypeError
,并且如果在引发错误之前添加任何属性,则会更改 target
对象。
¥In case of an error, for example if a property is non-writable, a
TypeError
is raised, and the target
object is
changed if any properties are added before the error is raised.
注意:
Object.assign()
不会在null
或undefined
源上抛出。¥Note:
Object.assign()
does not throw onnull
orundefined
sources.
示例
克隆对象
深度克隆警告
¥Warning for Deep Clone
对于 深度克隆,我们需要使用 structuredClone()
等替代方案,因为 Object.assign()
复制属性值。
¥For deep cloning, we need to use alternatives like structuredClone()
, because Object.assign()
copies property values.
如果源值是对对象的引用,则它仅复制引用值。
¥If the source value is a reference to an object, it only copies the reference value.
const obj1 = { a: 0, b: { c: 0 } };
const obj2 = Object.assign({}, obj1);
console.log(obj2); // { a: 0, b: { c: 0 } }
obj1.a = 1;
console.log(obj1); // { a: 1, b: { c: 0 } }
console.log(obj2); // { a: 0, b: { c: 0 } }
obj2.a = 2;
console.log(obj1); // { a: 1, b: { c: 0 } }
console.log(obj2); // { a: 2, b: { c: 0 } }
obj2.b.c = 3;
console.log(obj1); // { a: 1, b: { c: 3 } }
console.log(obj2); // { a: 2, b: { c: 3 } }
// Deep Clone
const obj3 = { a: 0, b: { c: 0 } };
const obj4 = structuredClone(obj3);
obj3.a = 4;
obj3.b.c = 4;
console.log(obj4); // { a: 0, b: { c: 0 } }
合并对象
合并具有相同属性的对象
¥Merging objects with same properties
const o1 = { a: 1, b: 1, c: 1 };
const o2 = { b: 2, c: 2 };
const o3 = { c: 3 };
const obj = Object.assign({}, o1, o2, o3);
console.log(obj); // { a: 1, b: 2, c: 3 }
这些属性将被参数顺序中稍后具有相同属性的其他对象覆盖。
¥The properties are overwritten by other objects that have the same properties later in the parameters order.
复制符号类型属性
原型链上的属性和不可枚举的属性不能被复制
¥Properties on the prototype chain and non-enumerable properties cannot be copied
const obj = Object.create(
// foo is on obj's prototype chain.
{ foo: 1 },
{
bar: {
value: 2, // bar is a non-enumerable property.
},
baz: {
value: 3,
enumerable: true, // baz is an own enumerable property.
},
},
);
const copy = Object.assign({}, obj);
console.log(copy); // { baz: 3 }
基元将被封装为对象
¥Primitives will be wrapped to objects
const v1 = "abc";
const v2 = true;
const v3 = 10;
const v4 = Symbol("foo");
const obj = Object.assign({}, v1, null, v2, undefined, v3, v4);
// Primitives will be wrapped, null and undefined will be ignored.
// Note, only string wrappers can have own enumerable properties.
console.log(obj); // { "0": "a", "1": "b", "2": "c" }
异常会中断正在进行的复制任务
¥Exceptions will interrupt the ongoing copying task
const target = Object.defineProperty({}, "foo", {
value: 1,
writable: false,
}); // target.foo is a read-only property
Object.assign(target, { bar: 2 }, { foo2: 3, foo: 3, foo3: 3 }, { baz: 4 });
// TypeError: "foo" is read-only
// The Exception is thrown when assigning target.foo
console.log(target.bar); // 2, the first source was copied successfully.
console.log(target.foo2); // 3, the first property of the second source was copied successfully.
console.log(target.foo); // 1, exception is thrown here.
console.log(target.foo3); // undefined, assign method has finished, foo3 will not be copied.
console.log(target.baz); // undefined, the third source will not be copied either.
复制访问器
¥Copying accessors
const obj = {
foo: 1,
get bar() {
return 2;
},
};
let copy = Object.assign({}, obj);
console.log(copy);
// { foo: 1, bar: 2 }
// The value of copy.bar is obj.bar's getter's return value.
// This is an assign function that copies full descriptors
function completeAssign(target, ...sources) {
sources.forEach((source) => {
const descriptors = Object.keys(source).reduce((descriptors, key) => {
descriptors[key] = Object.getOwnPropertyDescriptor(source, key);
return descriptors;
}, {});
// By default, Object.assign copies enumerable Symbols, too
Object.getOwnPropertySymbols(source).forEach((sym) => {
const descriptor = Object.getOwnPropertyDescriptor(source, sym);
if (descriptor.enumerable) {
descriptors[sym] = descriptor;
}
});
Object.defineProperties(target, descriptors);
});
return target;
}
copy = completeAssign({}, obj);
console.log(copy);
// { foo:1, get bar() { return 2 } }
规范
Specification |
---|
ECMAScript Language Specification # sec-object.assign |
浏览器兼容性
BCD tables only load in the browser