--- title: Object.assign() slug: Web/JavaScript/Reference/Global_Objects/Object/assign tags: - JavaScript - Method - Object translation_of: Web/JavaScript/Reference/Global_Objects/Object/assign ---
Object.assign()
được sử dụng để sao chép các giá trị của tất cả thuộc tính có thể liệt kê từ một hoặc nhiều đối tượng nguồn đến một đối tượng đích. Nó sẽ trả về đối tượng đích đó.
{{EmbedInteractiveExample("pages/js/object-assign.html")}}
The source for this interactive example is stored in a GitHub repository. If you'd like to contribute to the interactive examples project, please clone https://github.com/mdn/interactive-examples and send us a pull request.
Object.assign(target, ...sources)
target
sources
(Các) Đối tượng đích
Các thuộc tính trong đối tượng đích sẽ bị ghi lại bởi các thuộc tính trong đối tượng nguồn nếu chúng có cùng key. Tương tự, các thuộc tính nguồn sau sẽ ghi đè lên những thuộc tính nguồn trước.
Phương thức Object.assign()
chỉ sao chép những giá trị liệt kê được và và các thuộc tính của bản thân nó đến đối tượng đích. Nó sử dụng [[Get]]
trên nguồn và [[Set]]
trên đích, vì vậy nó sẽ gọi các hàm getter và setter. Vì lý do đó nó chỉ định thuộc tính so với việc chỉ sao chép hoặc xác đinh các thuộc tính mới. Điều này có thể khiến nó không phù hợp khi gộp các thuộc tính mới vào một nguyên mẫu (prototype) nếu các nguồn gộp chứa các getter. Để sao chép các thuộc tính xác định, bao gồm cả khả năng đếm được vào trong các nguyên mẫu thì nên sử dụng {{jsxref("Object.getOwnPropertyDescriptor()")}} và {{jsxref("Object.defineProperty()")}} để thay thế.
Các thuộc tính {{jsxref("String")}} và {{jsxref("Symbol")}} đều được sao chép.
Trong trường hợp có một lỗi, như việc một thuộc tính không được phép ghi đè, một {{jsxref("TypeError")}} sẽ sinh ra, và đối tượng đích có thể được thay đổi nếu có bất kỳ thuộc tính nào đã được thêm vào trước khi lỗi được sinh ra.
Chú ý rằng Object.assign()
không ném ra một {{jsxref("null")}} hoặc {{jsxref("undefined")}}.
var obj = { a: 1 }; var copy = Object.assign({}, obj); console.log(copy); // { a: 1 }
Với deep cloning, chúng ta cần sử dụng những lựa chọn khác khác bởi vì Object.assign()
sao chép các giá trị thuộc tính. Nếu giá trị nguồn là tham chiếu đến một object, nó chỉ sao chép gía trị tham chiếu đó.
function test() { 'use strict'; let a = { b: {c: 4} , d: { e: {f: 1} } }; let g = Object.assign({}, a); let h = JSON.parse(JSON.stringify(a)); console.log(JSON.stringify(g.d)); // { e: { f: 1 } } g.d.e = 32; console.log('g.d.e set to 32.'); // g.d.e set to 32. console.log(JSON.stringify(g)); // { b: { c: 4 }, d: { e: 32 } } console.log(JSON.stringify(a)); // { b: { c: 4 }, d: { e: 32 } } console.log(JSON.stringify(h)); // { b: { c: 4 }, d: { e: { f: 1 } } } h.d.e = 54; console.log('h.d.e set to 54.'); // h.d.e set to 54. console.log(JSON.stringify(g)); // { b: { c: 4 }, d: { e: 32 } } console.log(JSON.stringify(a)); // { b: { c: 4 }, d: { e: 32 } } console.log(JSON.stringify(h)); // { b: { c: 4 }, d: { e: 54 } } } test();
var o1 = { a: 1 }; var o2 = { b: 2 }; var o3 = { c: 3 }; var obj = Object.assign(o1, o2, o3); console.log(obj); // { a: 1, b: 2, c: 3 } console.log(o1); // { a: 1, b: 2, c: 3 }, object đích tự nó bị thay đổi.
var o1 = { a: 1, b: 1, c: 1 }; var o2 = { b: 2, c: 2 }; var o3 = { c: 3 }; var obj = Object.assign({}, o1, o2, o3); console.log(obj); // { a: 1, b: 2, c: 3 }
Các giá trị được ghi đè bởi các đối tượng khác mà chúng có chung các thuộc tính sau đó theo thứ tự các tham số.
var o1 = { a: 1 }; var o2 = { [Symbol('foo')]: 2 }; var obj = Object.assign({}, o1, o2); console.log(obj); // { a : 1, [Symbol("foo")]: 2 } (cf. bug 1207182 trên Firefox) Object.getOwnPropertySymbols(obj); // [Symbol(foo)]
var obj = Object.create({ foo: 1 }, { // foo ở trên mắt xích prototype của obj. bar: { value: 2 // bar chứa thuộc tính không liệt kê được. }, baz: { value: 3, enumerable: true // baz chứa thuộc tính liệt kê được. } }); var copy = Object.assign({}, obj); console.log(copy); // { baz: 3 }
var v1 = 'abc'; var v2 = true; var v3 = 10; var v4 = Symbol('foo'); var obj = Object.assign({}, v1, null, v2, undefined, v3, v4); // Sự nguyên bản sẽ bị gói lại, null và undefined sẽ bị bỏ qua. // Ghi chú,chỉ có string wrapper mới có thuộc tính liệt kê được. console.log(obj); // { "0": "a", "1": "b", "2": "c" }
var target = Object.defineProperty({}, 'foo', { value: 1, writable: false }); // target.foo chỉ read-only Object.assign(target, { bar: 2 }, { foo2: 3, foo: 3, foo3: 3 }, { baz: 4 }); // TypeError: "foo" là read-only // Trường hợp ngoại lệ được tạo ra khi gán target.foo console.log(target.bar); // 2, nguồn thứ nhất được sao chép thành công console.log(target.foo2); // 3, đặc tính thứ nhất của nguồn thứ 2 được chép thành công. console.log(target.foo); // 1, ngoại lệ được ném ra console.log(target.foo3); // undefined, phương thức gán đã hoàn tất, foo3 sẽ không bị sao chép console.log(target.baz); // undefined, nguồn thứ ba cũng không bị sao chép
var obj = { foo: 1, get bar() { return 2; } }; var copy = Object.assign({}, obj); console.log(copy); // { foo: 1, bar: 2 }, giá trị của copy.bar là giá trị return của getter của obj.bar. // Đây là function gán sao chép toàn bộ các mô tả. function completeAssign(target, ...sources) { sources.forEach(source => { let descriptors = Object.keys(source).reduce((descriptors, key) => { descriptors[key] = Object.getOwnPropertyDescriptor(source, key); return descriptors; }, {}); // Mặc định thì Object.assign sao chép cả Symbol thống kê được luôn Object.getOwnPropertySymbols(source).forEach(sym => { let descriptor = Object.getOwnPropertyDescriptor(source, sym); if (descriptor.enumerable) { descriptors[sym] = descriptor; } }); Object.defineProperties(target, descriptors); }); return target; } var copy = completeAssign({}, obj); console.log(copy); // { foo:1, get bar() { return 2 } }
{{Glossary("Polyfill","polyfill")}} không hỗ trợ các thuộc tính symbol, kể từ ES5 thì cũng không còn symbol nữa:
if (typeof Object.assign != 'function') { Object.assign = function(target, varArgs) { // .length của function là 2 'use strict'; if (target == null) { // TypeError nếu undefined hoặc null throw new TypeError('Cannot convert undefined or null to object'); } var to = Object(target); for (var index = 1; index < arguments.length; index++) { var nextSource = arguments[index]; if (nextSource != null) { // Bỏ qua nếu undefined hoặc null for (var nextKey in nextSource) { // Avoid bugs when hasOwnProperty is shadowed if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) { to[nextKey] = nextSource[nextKey]; } } } } return to; }; }
Specification | Status | Comment |
---|---|---|
{{SpecName('ESDraft', '#sec-object.assign', 'Object.assign')}} | {{Spec2('ESDraft')}} | |
{{SpecName('ES2015', '#sec-object.assign', 'Object.assign')}} | {{Spec2('ES2015')}} | Initial definition. |