--- title: delete operator slug: Web/JavaScript/Reference/Operators/delete translation_of: Web/JavaScript/Reference/Operators/delete ---
{{jsSidebar("Operators")}}

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.

{{EmbedInteractiveExample("pages/js/expressions-deleteoperator.html")}}

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 {{jsxref("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:

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

{{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ử 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 {{jsxref("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 {{jsxref("Array.splice", "splice")}}. Trong ví dụ sau, trees[3] bị xoá bỏ hoàn toàn khỏi mảng thông qua {{jsxref("Array.splice", "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
{{SpecName('ESDraft', '#sec-delete-operator', 'The delete Operator')}} {{Spec2('ESDraft')}}  
{{SpecName('ES6', '#sec-delete-operator', 'The delete Operator')}} {{Spec2('ES6')}}  
{{SpecName('ES5.1', '#sec-11.4.1', 'The delete Operator')}} {{Spec2('ES5.1')}}  
{{SpecName('ES1', '#sec-11.4.1', 'The delete Operator')}} {{Spec2('ES1')}} Định nghĩa lần đầu. Cài đặt trong JavaScript 1.2.

Trình duyệt hỗ trợ

{{Compat("javascript.operators.delete")}}

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 {{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.

Xem thêm