aboutsummaryrefslogtreecommitdiff
path: root/files/vi/web/javascript/reference/global_objects/object/assign/index.html
blob: 2f5b00f1ec84749ce621645812e2ba670ba26f13 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
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()")}}{{jsxref("Object.defineProperty()")}} để thay thế.</p>

<p>Các thuộc tính {{jsxref("String")}}{{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 =&gt; {
    let descriptors = Object.keys(source).reduce((descriptors, key) =&gt; {
      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 =&gt; {
      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 &lt; 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>