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
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
|
---
title: delete operator
slug: Web/JavaScript/Reference/Operators/delete
translation_of: Web/JavaScript/Reference/Operators/delete
---
<div>{{jsSidebar("Operators")}}</div>
<p><span class="seoSummary"><strong>Toán tử <code>delete</code></strong> của JavaScript loại bỏ một thuộc tính khỏi object; nếu không tồn tại tham chiếu tới thuộc tính, nó sẽ tự động giải phóng.</span></p>
<div>{{EmbedInteractiveExample("pages/js/expressions-deleteoperator.html")}}</div>
<h2 id="Cú_pháp">Cú pháp</h2>
<pre class="syntaxbox">delete <em>expression</em> </pre>
<p>với <em>expression</em> thực thi thành tham chiếu đến <a href="/en-US/docs/Glossary/property/JavaScript">thuộc tính</a> nào đó, tức là:</p>
<pre class="syntaxbox">delete <em>object.property</em>
delete <em>object</em>['<em>property</em>']
</pre>
<h3 id="Tham_số">Tham số</h3>
<dl>
<dt><code>object</code></dt>
<dd>Tên object, hoặc biểu thức thực thi tới object.</dd>
<dt><code>property</code></dt>
<dd>Thuộc tính muốn xoá.</dd>
</dl>
<h3 id="Giá_trị_trả_về">Giá trị trả về</h3>
<p><code>true</code> cho mọi trường hợp trừ khi thuộc tính là <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty">own</a> <a href="/en-US/docs/Web/JavaScript/Reference/Errors/Cant_delete">non-configurable</a>, trong trường hợp đó, trả về <code>false</code> trong chế độ non-strict.</p>
<h3 id="Ngoại_lệ">Ngoại lệ</h3>
<p>Quăng {{jsxref("TypeError")}} trong <a href="/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope/Strict_mode"> chế độ strict</a> nếu thuộc tính là own non-configurable.</p>
<h2 id="Mô_tả">Mô tả</h2>
<p>Khác với suy nghĩ của nhiều người, toán tử <code>delete</code> <strong>không</strong> trực tiếp giải phóng bộ nhớ. Quản lý bộ nhớ được thực hiện trung gian qua việc bẻ tham chiếu. Xem trang <a href="/en-US/docs/Web/JavaScript/Memory_Management">quản lý bộ nhớ</a> để biết thêm chi tiết.</p>
<p>Toán tử <code><strong>delete</strong></code> loại bỏ thuộc tính xác định trong object. Nếu xoá thành công, nó sẽ trả về <code>true</code>, ngoài ra thì <code>false</code>. Tuy nhiên, hãy lưu ý những kịch bản có thể xảy đến sau đây:</p>
<ul>
<li>Nếu thuộc tính muốn xoá không tồn tại, <code>delete</code> sẽ không có tác dụng và sẽ trả về <code>true</code></li>
<li>Nếu tồn tại thuộc tính có cùng tên trong prototype nối với object, thì sau khi xoá xong, object sẽ dùng thuộc tính từ prototype đó (nói cách khác, <code>delete</code> chỉ có tác dụng với những thuộc tính của riêng object).</li>
<li>Bất cứ thuộc tính nào được khởi tạo bằng {{jsxref("Statements/var","var")}} không thể bị xoá khỏi phạm vi toàn cục hoặc phạm vi hàm.
<ul>
<li>Vì thế, <code>delete</code> không thể xoá bất cứ hàm nào trong phạm vi toàn cục (cho dù là một phần của định nghĩa hàm hay biểu thức hàm).</li>
<li>Các hàm là một phần của object (tách biệt với phạm vi toàn cục) có thể bị xoá với <code>delete</code>.</li>
</ul>
</li>
<li>Bất cứ thuộc tính nào được khởi tạo bởi {{jsxref("Statements/let","let")}} hoặc {{jsxref("Statements/const","const")}} không thể bị xoá khỏi phạm vi mà chúng được khai báo.</li>
<li>Thuộc tính không-thể-cấu-hình không thể bị loại bỏ. Các thuộc tính này bao gồm các object dựng sẵn như {{jsxref("Math")}}, {{jsxref("Array")}}, {{jsxref("Object")}} và thuộc tính được tạo ra như thuộc tính không-thể-cấu-hình bằng phương thức như là {{jsxref("Object.defineProperty()")}}.</li>
</ul>
<p>Snippet sau đưa ra ví dụ đơn giản:</p>
<pre class="brush: js">var Employee = {
age: 28,
name: 'abc',
designation: 'developer'
}
console.log(delete Employee.name); // trả về true
console.log(delete Employee.age); // trả về true
// Khi cố xoá một thuộc tính không tồn tại
// sẽ trả về giá trị true
console.log(delete Employee.salary); // trả về true
</pre>
<h3 id="Thuộc_tính_không-thể-cấu-hình"><strong>Thuộc tính không-thể-cấu-hình</strong></h3>
<p>Khi một thuộc tính được đánh dấu không-thể-cấu-hình, <code>delete</code> không có tác dụng nào, và sẽ trả về <code>false</code>. Trong chế độ strict, lỗi <code>TypeError</code> sẽ nhảy ra.</p>
<pre class="brush: js">var Employee = {};
Object.defineProperty(Employee, 'name', {configurable: false});
console.log(delete Employee.name); // trả về false
</pre>
<p>{{jsxref("Statements/var","var")}}, {{jsxref("Statements/let","let")}} và {{jsxref("Statements/const","const")}} tạo ra thuộc tính không-thể-cấu-hình mà không thể xoá bằng toán tử <code>delete</code>:</p>
<pre class="brush: js">var nameOther = 'XYZ';
// Ta có thể truy cập vào thuộc tính toàn cục này thông qua:
Object.getOwnPropertyDescriptor(window, 'nameOther');
// output: Object {value: "XYZ",
// writable: true,
// enumerable: true,
// <strong>configurable: false</strong>}
// Bởi vì "nameOther" được thêm vào nhờ dùng
// từ khoá var, nên nó được đánh dấu là "không-thể-cấu-hình"
delete nameOther; // trả về false</pre>
<p>Trong chế độ strict, ngoại lệ sẽ quăng ra.</p>
<h3 id="Chế_độ_strict_và_non-strict"><strong>Chế độ strict và non-strict</strong></h3>
<p>Khi ở trong chế độ strict, nếu <code>delete</code> được dùng để tham chiếu trực tiếp tới một biến, một đối số của hàm hoặc tên hàm, nó sẽ quăng ra {{jsxref("SyntaxError")}}<strong>.</strong></p>
<p>Bất cứ biến nào được định nghĩa với <code>var</code> đều được đánh dấu là không-thể-cấu-hình. Trong ví dụ sau đây, <code>salary</code> là không-thể-cấu-hình và không thể xoá. Trong chế độ non-strict, phép toán <code>delete</code> sẽ trả về <code>false</code>.</p>
<pre class="brush: js">function Employee() {
delete salary;
var salary;
}
Employee();
</pre>
<p>Cùng xem mã nguồn tương tự hoạt động ra sao trong chế độ strict nhé. Thay vì trả về <code>false</code>, <code>SyntaxError</code> được quăng ra.</p>
<pre class="brush: js">"use strict";
function Employee() {
delete salary; // SyntaxError
var salary;
}
// Tương tự, bất cứ truy nhập trực tiếp nào vào hàm
// dùng delete đều quăng ra SyntaxError
function DemoFunction() {
//vài đoạn code
}
delete DemoFunction; // SyntaxError
</pre>
<h2 id="Ví_dụ">Ví dụ</h2>
<pre class="brush: js">// Tạo thuộc tính adminName trên phạm vi toàn cục.
adminName = 'xyz';
// Tạo thuộc tính empCount trên phạm vi toàn cục =.
// Vì dùng var, thuộc tính này được đánh dấu là không-thể-cấu-hình.
// Điều tương tự xảy đến với let và const.
var empCount = 43;
EmployeeDetails = {
name: 'xyz',
age: 5,
designation: 'Developer'
};
// adminName là thuộc tính trên phạm vi toàn cục.
// Nó có thể bị xoá bởi được khởi tạo mà không dùng var,
// và vì thế khả cấu.
delete adminName; // trả về true
// Ngược lại, empCount không khả cấu
// bởi dùng var.
delete empCount; // trả về false
// Có thể dùng delete để loại bỏ thuộc tính khỏi object.
delete EmployeeDetails.name; // trả về true
<strong>// </strong>Thậm chí thuộc tính không tồn tại, delete vẫn trả về "true".
delete EmployeeDetails.salary; // trả về true
// delete không có tác dụng với thuộc tính dựng sẵn.
delete Math.PI; // trả về false
// EmployeeDetails là thuộc tính trong phạm vi toàn cục.
// Vì được khởi tạo mà không dùng "var", nó được đánh dấu là khả cấu.
delete EmployeeDetails; // trả về true
function f() {
var z = 44;
// delete không có tác dụng với tên biến cục bộ
delete z; // trả về false
}
</pre>
<h3 id="delete_và_prototype_chain"><code>delete</code> và prototype chain</h3>
<p>Trong ví dụ sau, ta sẽ xoá một thuộc tính riêng của object mà vẫn tồn tại thuộc tính cùng tên trong prototype chain:</p>
<pre class="brush: js">function Foo() {
this.bar = 10;
}
Foo.prototype.bar = 42;
var foo = new Foo();
// foo.bar liên kết với
// thuộc tính riêng.
console.log(foo.bar); // 10
// Xoá thuộc tính riêng trên
// foo object.
delete foo.bar; // trả về true
// foo.bar vẫn sẵn sàng trên
// prototype chain.
console.log(foo.bar); // 42
// Xoá thuộc tính trên prototype.
delete Foo.prototype.bar; // trả về true
// Thuộc tính "bar" không còn có thể
// kể thừa từ Foo bởi nó đã bị xoá
console.log(foo.bar); // undefined</pre>
<h3 id="Xoá_phần_tử_mảng"><strong>Xoá phần tử mảng</strong></h3>
<p>Khi bạn xoá phần tử mảng, độ dài mảng không bị ảnh hưởng. Thậm chí khi bạn xoá phần tử cuối của mảng cũng không thay đổi được điều này.</p>
<p>Khi toán tử <code>delete</code> loại bỏ một phần tử mảng, phần tử đó không còn trong mảng. Trong ví dụ sau, <code>trees[3]</code> bị xoá bởi <code>delete</code>.</p>
<pre class="brush: js">var trees = ['redwood', 'bay', 'cedar', 'oak', 'maple'];
delete trees[3];
if (3 in trees) {
// không thực thi đoạn code này
}</pre>
<p>Nếu bạn muốn giữ lại phần tử mảng và gán giá trị undefined cho nó, hãy dùng <code>undefined</code> thay vì toán tử <code>delete</code>. Trong ví dụ sau, <code>trees[3]</code> được gán giá trị undefined, nhưng phần tử mảng vẫn tồn tại:</p>
<pre class="brush: js">var trees = ['redwood', 'bay', 'cedar', 'oak', 'maple'];
trees[3] = undefined;
if (3 in trees) {
// đoạn code trong này sẽ chạy
}</pre>
<p>Thay vì thế, nếu muốn loại bỏ phần tử mảng bằng cách thay đổi nội dung của mảng, hãy dùng phương thức <code>{{jsxref("Array.splice", "splice")}}</code>. Trong ví dụ sau, <code>trees[3]</code> bị xoá bỏ hoàn toàn khỏi mảng thông qua <code>{{jsxref("Array.splice", "splice")}}</code>:</p>
<pre class="brush: js">var trees = ['redwood', 'bay', 'cedar', 'oak', 'maple'];
trees.splice(3,1);
console.log(trees); // ["redwood", "bay", "cedar", "maple"]
</pre>
<h2 id="Đặc_Đặc_tả">Đặc Đặc 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-delete-operator', 'The delete Operator')}}</td>
<td>{{Spec2('ESDraft')}}</td>
<td> </td>
</tr>
<tr>
<td>{{SpecName('ES6', '#sec-delete-operator', 'The delete Operator')}}</td>
<td>{{Spec2('ES6')}}</td>
<td> </td>
</tr>
<tr>
<td>{{SpecName('ES5.1', '#sec-11.4.1', 'The delete Operator')}}</td>
<td>{{Spec2('ES5.1')}}</td>
<td> </td>
</tr>
<tr>
<td>{{SpecName('ES1', '#sec-11.4.1', 'The delete Operator')}}</td>
<td>{{Spec2('ES1')}}</td>
<td>Định nghĩa lần đầu. Cài đặt trong JavaScript 1.2.</td>
</tr>
</tbody>
</table>
<h2 id="Trình_duyệt_hỗ_trợ">Trình duyệt hỗ trợ</h2>
<p>{{Compat("javascript.operators.delete")}}</p>
<h2 id="Ghi_chú_Cross-browser">Ghi chú Cross-browser</h2>
<p>Although ECMAScript makes iteration order of objects implementation-dependent, it may appear that all major browsers support an iteration order based on the earliest added property coming first (at least for properties not on the prototype). However, in the case of Internet Explorer, when one uses <code>delete</code> on a property, some confusing behavior results, preventing other browsers from using simple objects like object literals as ordered associative arrays. In Explorer, while the property <em>value</em> is indeed set to undefined, if one later adds back a property with the same name, the property will be iterated in its <em>old</em> position--not at the end of the iteration sequence as one might expect after having deleted the property and then added it back.</p>
<p>If you want to use an ordered associative array in a cross-browser environment, use a {{jsxref("Map")}} object if available, or simulate this structure with two separate arrays (one for the keys and the other for the values), or build an array of single-property objects, etc.</p>
<h2 id="Xem_thêm">Xem thêm</h2>
<ul>
<li><a href="http://perfectionkills.com/understanding-delete/">Phân tích sâu về delete</a></li>
<li>{{jsxref("Reflect.deleteProperty()")}}</li>
<li>{{jsxref("Map.prototype.delete()")}}</li>
</ul>
|