Xóa các đối tượng trong JavaScript


359

Tôi hơi bối rối với deletetoán tử của JavaScript . Lấy đoạn mã sau:

var obj = {
    helloText: "Hello World!"
};

var foo = obj;

delete obj;

Sau khi đoạn mã này được thực thi, objnull, nhưng foovẫn đề cập đến một đối tượng chính xác như thế nào obj. Tôi đoán đối tượng này là cùng một đối tượng foođã chỉ.

Điều này làm tôi bối rối, bởi vì tôi dự đoán rằng việc viết delete objđã xóa đối tượng objđược trỏ đến trong bộ nhớ, không chỉ là biến obj.

Đây có phải là do Trình thu gom rác của JavaScript đang hoạt động trên cơ sở giữ lại / phát hành, do đó nếu tôi không có bất kỳ biến nào khác trỏ đến đối tượng, nó sẽ bị xóa khỏi bộ nhớ?

(Nhân tiện, thử nghiệm của tôi đã được thực hiện trong Safari 4.)



Bài viết đầy đủ về từ khóa xóa webcache.googleusercontent.com/
Vitim.us

2
Liên kết ở trên phải là: perfectionkills.com/under
Hiểu

1
@Steve Harrison xóa không phải để xóa một đối tượng trong javascript xóa sử dụng để xóa khóa đối tượng trong trường hợp var obj = { helloText: "Hello World!" }; var foo = obj; delete obj;đối tượng của bạn không bị xóa kiểm tra objsử dụng xóa: delete obj.helloTextvà sau đó kiểm trafoo now foo is an empty object
Umair Ahmed

2
@UmairAhmed, Bản dịch miễn phí: "" " deletekhông phải để xóa các đối tượng trong javascript. deleteĐược sử dụng để xóa khóa đối tượng. Trong trường hợp của bạn var obj = { helloText: "Hello World!" }; var foo = obj; delete obj;, đối tượng không bị xóa. Hãy kiểm tra obj. Tiếp theo, hãy chạy delete obj.helloTextvà bạn có thể thấy rằng foobây giờ chỉ vào một khoảng trống đối tượng. "" "
Pacerier

Câu trả lời:


448

Toán tử xóa chỉ xóa một tham chiếu, không bao giờ là một đối tượng. Nếu nó tự xóa đối tượng, các tham chiếu còn lại sẽ bị treo lủng lẳng, như xóa C ++. (Và việc truy cập một trong số chúng sẽ gây ra sự cố. Để làm cho tất cả chúng biến thành null có nghĩa là có thêm công việc khi xóa hoặc thêm bộ nhớ cho mỗi đối tượng.)

Vì Javascript là rác được thu thập, bạn không cần phải tự xóa các đối tượng - chúng sẽ bị xóa khi không còn cách nào để tham khảo chúng nữa.

Có thể hữu ích để xóa các tham chiếu đến một đối tượng nếu bạn kết thúc với chúng, bởi vì điều này cung cấp cho trình thu gom rác thêm thông tin về những gì có thể được thu hồi. Nếu các tham chiếu vẫn còn cho một đối tượng lớn, điều này có thể khiến nó không được công nhận - ngay cả khi phần còn lại của chương trình của bạn không thực sự sử dụng đối tượng đó.


23
Các deletetừ khóa chỉ hoạt động đối với tài sản của một đối tượng, không biến. perfectionkills.com/under
Hiểu-dete

1
@AlexJM Vâng, câu trả lời tiếp theo từ Guffa (và ý kiến ​​của nó) thảo luận về điều này một cách chi tiết.
Jesse Rusak

1
Một thuộc tính của một đối tượng có thể là một đối tượng khác. Ví dụ; var obj = {a: {}}; delete obj.a;
Alex Mund

2
Nhưng ... không phải là các biến thực sự thuộc tính của window?
RedClover

3
@Soaku không phải biến cục bộ. (ví dụ: những người được tuyên bố với var)
Jesse Rusak

162

Các deletelệnh không ảnh hưởng đến các biến thông thường, chỉ có tài sản. Sau deletelệnh mà thuộc tính không có giá trị null, nó hoàn toàn không tồn tại.

Nếu thuộc tính là một tham chiếu đối tượng, deletelệnh sẽ xóa thuộc tính nhưng không phải đối tượng. Trình thu gom rác sẽ chăm sóc đối tượng nếu nó không có tài liệu tham khảo nào khác.

Thí dụ:

var x = new Object();
x.y = 42;

alert(x.y); // shows '42'

delete x; // no effect
alert(x.y); // still shows '42'

delete x.y; // deletes the property
alert(x.y); // shows 'undefined'

(Đã thử nghiệm trên Firefox.)


39
Nếu điều này được thực thi trong phạm vi toàn cục, xbiến của bạn sẽ trở thành một thuộc tính trên windowđối tượng toàn cục và delete x;thực sự loại bỏ xhoàn toàn biến đó.
Lưỡi liềm tươi

18
@crescentfresh: Nó chỉ là một tài sản nếu nó được khai báo ngầm. Nếu nó được tuyên bố rõ ràng như trong ví dụ, thì đó là biến toàn cục và không thể xóa được.
Guffa

4
@Tarynn: Tôi hiểu rồi, đó là vấn đề. Nếu bạn làm điều này trong bảng điều khiển, vì một số lý do xsẽ không phải là một biến thích hợp trong một số trình duyệt, mà là một thuộc tính trong windowđối tượng. Tất nhiên đây là một vấn đề với bàn điều khiển và không phản ánh cách thức mã được thực thi thông thường.
Guffa

2
@Guffa Sau một loạt các nghiên cứu tôi phải thừa nhận nó có lẽ là một điều tốt tôi không có đủ đại diện để bỏ phiếu. Lời xin lỗi chân thành nhất của tôi và cảm ơn vì đã dành thời gian để cho tôi thấy điều gì đang xảy ra ... Đây là một khám phá sâu sắc: perfectionkills.com/under
Hiểu

2
@chao: Mình hiểu rồi. Bạn đang gặp vấn đề tương tự như Tarynn (xem các bình luận trước đó). Khi bạn làm điều này trong bàn điều khiển, nó không hoạt động giống như trong mã thực.
Guffa

56

"Các biến được khai báo ngầm" là các thuộc tính của đối tượng toàn cục, vì vậy xóa hoạt động trên chúng giống như nó hoạt động trên bất kỳ thuộc tính nào. Các biến được khai báo với var là không thể phá hủy.


53
Tôi không bao giờ nhận ra var là rất xấu.
Gavin

1
Đây là một điểm tuyệt vời và một gotcha JS. Mọi người đã quen với việc xóa các cửa sổ và sau đó tự hỏi tại sao họ không thể làm tương tự với các biến cục bộ.
Welbornio

2
Cùng đi cho let.
Pacerier


4

delete không được sử dụng để xóa một đối tượng trong java Script.

deleteđược sử dụng để loại bỏ một object keytrong trường hợp của bạn

var obj = { helloText: "Hello World!" }; 
var foo = obj;
delete obj;

Đối tượng không bị xóa kiểm tra obj vẫn lấy cùng một giá trị xóa sử dụng:

delete obj.helloText

và sau đó kiểm tra obj, foo, cả hai đều là đối tượng trống rỗng.


2

Chỉ cần tìm thấy một jsperf bạn có thể xem xét thú vị về vấn đề này. (nó có thể hữu ích để giữ nó xung quanh để hoàn thành bức tranh)

Nó so sánh xóa , thiết lập null và thiết lập không xác định .

Nhưng hãy nhớ rằng nó sẽ kiểm tra trường hợp khi bạn xóa / đặt thuộc tính nhiều lần.



1

IE 5 đến 8 có một lỗi trong đó việc sử dụng xóa trên các thuộc tính của đối tượng máy chủ (Window, Global, DOM, v.v.) ném TypeError "đối tượng không hỗ trợ hành động này".

var el=document.getElementById("anElementId");
el.foo = {bar:"baz"};
try{
    delete el.foo;
}catch(){
    //alert("Curses, drats and double double damn!");
    el.foo=undefined; // a work around
}

Sau này nếu bạn cần kiểm tra nơi tài sản có ý nghĩa sử dụng giá trị đầy đủ el.foo !== undefined"foo" in el sẽ luôn trả về true trong IE.

Nếu bạn thực sự cần tài sản để thực sự biến mất ...

function hostProxy(host){
    if(host===null || host===undefined) return host;
    if(!"_hostProxy" in host){
       host._hostproxy={_host:host,prototype:host};
    }
    return host._hostproxy;
}
var el=hostProxy(document.getElementById("anElementId"));
el.foo = {bar:"baz"};

delete el.foo; // removing property if a non-host object

nếu bạn cần sử dụng đối tượng máy chủ với máy chủ api ...

el.parent.removeChild(el._host);

1

Tôi tình cờ thấy bài viết này trong tìm kiếm của tôi cho cùng một câu trả lời. Điều cuối cùng tôi làm chỉ là bật ra obj.pop()tất cả các giá trị / đối tượng được lưu trữ trong đối tượng của tôi để tôi có thể sử dụng lại đối tượng. Không chắc đây có phải là thực hành xấu hay không. Kỹ thuật này có ích cho tôi khi kiểm tra mã của mình trong các công cụ Chrome Dev hoặc FireFox Web Console.


1

Công việc này đối với tôi, mặc dù nó không phải là một thực hành tốt. Nó chỉ đơn giản là xóa tất cả các yếu tố liên quan mà đối tượng thuộc về.

 for (element in homeService) {
          delete homeService[element];
  }

thực hành tốt nhất là gì? Tôi nhớ đọc rằng toán tử xóa không thực tế nhất để xóa các thuộc tính đối tượng. Tôi tin rằng tôi đã đọc điều này trong cuốn sách JavaScript của Crockford, nhưng không thể khai thác nó vào lúc này.
zero_cool

0

Đặt một biến để nullđảm bảo phá vỡ mọi tham chiếu đến các đối tượng trong tất cả các trình duyệt, bao gồm các tham chiếu vòng tròn được tạo giữa các thành phần DOM và phạm vi Javascript. Bằng cách sử dụng deletelệnh, chúng tôi sẽ đánh dấu các đối tượng sẽ bị xóa trong lần chạy tiếp theo của bộ sưu tập Rác, nhưng nếu có nhiều biến tham chiếu đến cùng một đối tượng, xóa một biến duy nhất S NOT KHÔNG giải phóng đối tượng, nó sẽ chỉ xóa liên kết giữa biến đó và đối tượng. Và trong lần chạy tiếp theo của bộ sưu tập Rác, chỉ có biến sẽ được làm sạch.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.