Toán tử delete
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.
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.
Cú pháp
delete expression
với expression thực thi thành tham chiếu đến thuộc tính nào đó, tức là:
delete object.property delete object['property']
Tham số
object
- Tên object, hoặc biểu thức thực thi tới object.
property
- Thuộc tính muốn xoá.
Giá trị trả về
true
cho mọi trường hợp trừ khi thuộc tính là own non-configurable, trong trường hợp đó, trả về false
trong chế độ non-strict.
Ngoại lệ
Quăng TypeError
trong chế độ strict nếu thuộc tính là own non-configurable.
Mô tả
Khác với suy nghĩ của nhiều người, toán tử delete
không 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 quản lý bộ nhớ để biết thêm chi tiết.
Toán tử delete
loại bỏ thuộc tính xác định trong object. Nếu xoá thành công, nó sẽ trả về true
, ngoài ra thì false
. Tuy nhiên, hãy lưu ý những kịch bản có thể xảy đến sau đây:
- Nếu thuộc tính muốn xoá không tồn tại,
delete
sẽ không có tác dụng và sẽ trả vềtrue
- 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,
delete
chỉ có tác dụng với những thuộc tính của riêng object). - Bất cứ thuộc tính nào được khởi tạo bằng
var
không thể bị xoá khỏi phạm vi toàn cục hoặc phạm vi hàm.- Vì thế,
delete
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). - 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
delete
.
- Vì thế,
- Bất cứ thuộc tính nào được khởi tạo bởi
let
hoặcconst
không thể bị xoá khỏi phạm vi mà chúng được khai báo. - 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ư
Math
,Array
,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àObject.defineProperty()
.
Snippet sau đưa ra ví dụ đơn giản:
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
Thuộc tính không-thể-cấu-hình
Khi một thuộc tính được đánh dấu không-thể-cấu-hình, delete
không có tác dụng nào, và sẽ trả về false
. Trong chế độ strict, lỗi TypeError
sẽ nhảy ra.
var Employee = {};
Object.defineProperty(Employee, 'name', {configurable: false});
console.log(delete Employee.name); // trả về false
var
, let
và 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ử delete
:
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,
// configurable: false}
// 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
Trong chế độ strict, ngoại lệ sẽ quăng ra.
Chế độ strict và non-strict
Khi ở trong chế độ strict, nếu delete
đượ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 SyntaxError
.
Bất cứ biến nào được định nghĩa với var
đều được đánh dấu là không-thể-cấu-hình. Trong ví dụ sau đây, salary
là không-thể-cấu-hình và không thể xoá. Trong chế độ non-strict, phép toán delete
sẽ trả về false
.
function Employee() {
delete salary;
var salary;
}
Employee();
Cùng xem mã nguồn tương tự hoạt động ra sao trong chế độ strict nhé. Thay vì trả về false
, SyntaxError
được quăng ra.
"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
Ví dụ
// 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
// 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
}
delete
và prototype chain
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:
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
Xoá phần tử mảng
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.
Khi toán tử delete
loại bỏ một phần tử mảng, phần tử đó không còn trong mảng. Trong ví dụ sau, trees[3]
bị xoá bởi delete
.
var trees = ['redwood', 'bay', 'cedar', 'oak', 'maple'];
delete trees[3];
if (3 in trees) {
// không thực thi đoạn code này
}
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 undefined
thay vì toán tử delete
. Trong ví dụ sau, trees[3]
được gán giá trị undefined, nhưng phần tử mảng vẫn tồn tại:
var trees = ['redwood', 'bay', 'cedar', 'oak', 'maple'];
trees[3] = undefined;
if (3 in trees) {
// đoạn code trong này sẽ chạy
}
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
. Trong ví dụ sau, splice
trees[3]
bị xoá bỏ hoàn toàn khỏi mảng thông qua
:splice
var trees = ['redwood', 'bay', 'cedar', 'oak', 'maple'];
trees.splice(3,1);
console.log(trees); // ["redwood", "bay", "cedar", "maple"]
Đặc Đặc tả
Specification | Status | Comment |
---|---|---|
ECMAScript (ECMA-262) The definition of 'The delete Operator' in that specification. |
Living Standard | |
ECMAScript 2015 (6th Edition, ECMA-262) The definition of 'The delete Operator' in that specification. |
Standard | |
ECMAScript 5.1 (ECMA-262) The definition of 'The delete Operator' in that specification. |
Standard | |
ECMAScript 1st Edition (ECMA-262) The definition of 'The delete Operator' in that specification. |
Standard | Định nghĩa lần đầu. Cài đặt trong JavaScript 1.2. |
Trình duyệt hỗ trợ
BCD tables only load in the browser
Ghi chú Cross-browser
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 delete
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 value is indeed set to undefined, if one later adds back a property with the same name, the property will be iterated in its old position--not at the end of the iteration sequence as one might expect after having deleted the property and then added it back.
If you want to use an ordered associative array in a cross-browser environment, use a 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.