diff options
Diffstat (limited to 'files/vi/web/javascript/reference/global_objects/object/assign/index.html')
-rw-r--r-- | files/vi/web/javascript/reference/global_objects/object/assign/index.html | 259 |
1 files changed, 259 insertions, 0 deletions
diff --git a/files/vi/web/javascript/reference/global_objects/object/assign/index.html b/files/vi/web/javascript/reference/global_objects/object/assign/index.html new file mode 100644 index 0000000000..2f5b00f1ec --- /dev/null +++ b/files/vi/web/javascript/reference/global_objects/object/assign/index.html @@ -0,0 +1,259 @@ +--- +title: Object.assign() +slug: Web/JavaScript/Reference/Global_Objects/Object/assign +tags: + - JavaScript + - Method + - Object +translation_of: Web/JavaScript/Reference/Global_Objects/Object/assign +--- +<div>{{JSRef}}</div> + +<p><strong><code>Object.assign()</code></strong> đượ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 đó.</p> + +<p>{{EmbedInteractiveExample("pages/js/object-assign.html")}}</p> + +<p>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 <a href="https://github.com/mdn/interactive-examples">https://github.com/mdn/interactive-examples</a> and send us a pull request.</p> + +<h2 id="Cú_pháp">Cú pháp</h2> + +<pre class="syntaxbox">Object.assign(<var>target</var>, ...<var>sources</var>)</pre> + +<h3 id="Các_tham_số">Các tham số</h3> + +<dl> + <dt><code>target</code></dt> + <dd>Đối tượng đích</dd> + <dt><code>sources</code></dt> + <dd>Các đối tượng nguồn</dd> +</dl> + +<h3 id="Giá_trị_trả_về">Giá trị trả về</h3> + +<p>(Các) Đối tượng đích</p> + +<h2 id="Mô_tả">Mô tả</h2> + +<p>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. </p> + +<p>Phương thức <code>Object.assign()</code> chỉ sao chép những giá trị <em>liệt kê được</em> và và các thuộc tính <em>của bản thân</em> nó đến đối tượng đích. Nó sử dụng <code>[[Get]]</code> trên nguồn và <code>[[Set]]</code> trên đích, vì vậy nó sẽ gọi các hàm getter và setter. Vì lý do đó nó <em>chỉ định</em> 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ế.</p> + +<p>Các thuộc tính {{jsxref("String")}} và {{jsxref("Symbol")}} đều được sao chép.</p> + +<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.</p> + +<p>Chú ý rằng <code>Object.assign()</code> không ném ra một {{jsxref("null")}} hoặc {{jsxref("undefined")}}.</p> + +<h2 id="Ví_dụ">Ví dụ</h2> + +<h3 id="Sao_chép_một_object">Sao chép một object</h3> + +<pre class="brush: js">var obj = { a: 1 }; +var copy = Object.assign({}, obj); +console.log(copy); // { a: 1 } +</pre> + +<h3 id="Deep_Clone" name="Deep_Clone">Cảnh báo về Deep Clone</h3> + +<p>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ì <code>Object.assign()</code> 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 đó. </p> + +<pre class="brush: js">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();</pre> + +<h3 id="Gộp_các_object">Gộp các object</h3> + +<pre class="brush: js">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.</pre> + +<h3 id="Gộp_các_đối_tượng_với_cùng_giá_trị">Gộp các đối tượng với cùng giá trị</h3> + +<pre class="brush: js">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 }</pre> + +<p>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ố.</p> + +<h3 id="Sao_chép_thuộc_tính_symbol-typed">Sao chép thuộc tính symbol-typed</h3> + +<pre class="brush: js">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)] +</pre> + +<h3 id="Các_thuộc_tính_trên_chuỗi_nguyên_mẫu_và_các_thuộc_tính_không_có_khả_năng_đếm_được_thì_không_thể_sao_chép.">Các thuộc tính trên chuỗi nguyên mẫu và các thuộc tính không có khả năng đếm được thì không thể sao chép. </h3> + +<pre class="brush: js">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 } +</pre> + +<h3 id="Các_giá_trị_nguyên_thủy_sẽ_được_gói_thành_các_đối_tượng.">Các giá trị nguyên thủy sẽ được gói thành các đối tượng.</h3> + +<pre class="brush: js">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" } +</pre> + +<h3 id="Các_ngoại_lệ_sẽ_làm_gián_đoạn_quá_trình_sao_chép.">Các ngoại lệ sẽ làm gián đoạn quá trình sao chép.</h3> + +<pre class="brush: js">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 +</pre> + +<h3 id="Sao_chép_các_trình_truy_cập_accessor">Sao chép các trình truy cập (accessor)</h3> + +<pre class="brush: js">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 } } +</pre> + +<h2 id="Polyfill">Polyfill</h2> + +<p> {{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:</p> + +<pre class="brush: js">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; + }; +} +</pre> + +<h2 id="Đặc_tính_kỹ_thuật">Đặc tính kỹ thuật</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">Specification</th> + <th scope="col">Status</th> + <th scope="col">Comment</th> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-object.assign', 'Object.assign')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td></td> + </tr> + <tr> + <td>{{SpecName('ES2015', '#sec-object.assign', 'Object.assign')}}</td> + <td>{{Spec2('ES2015')}}</td> + <td>Initial definition.</td> + </tr> + </tbody> +</table> + +<h2 id="Tương_thích_trình_duyệt">Tương thích trình duyệt</h2> + +<div>{{Compat("javascript.builtins.Object.assign")}}</div> + +<div id="compat-mobile"></div> + +<h2 id="Xem_thêm">Xem thêm</h2> + +<ul> + <li>{{jsxref("Object.defineProperties()")}}</li> + <li><a href="/en-US/docs/Web/JavaScript/Enumerability_and_ownership_of_properties">Enumerability and ownership of properties</a></li> +</ul> |