Có an toàn để xóa một thuộc tính đối tượng trong khi lặp lại chúng không?


100

Khi lặp qua các thuộc tính của một đối tượng, có an toàn để xóa chúng khi đang ở trong vòng lặp for-in không?

Ví dụ:

for (var key in obj) {
    if (!obj.hasOwnProperty(key)) continue;

    if (shouldDelete(obj[key])) {
        delete obj[key];
    }
}

Trong nhiều ngôn ngữ khác, việc lặp lại một mảng hoặc từ điển và xóa bên trong là không an toàn. Nó ổn trong JS?

(Tôi đang sử dụng thời gian chạy Spidermonkey của Mozilla.)


Tôi đã bắt đầu nhận tiền thưởng cho câu hỏi này vì tôi nghĩ rằng câu trả lời hiện tại không đủ và không trả lời câu hỏi như đã trình bày . Cũng vui lòng bao gồm một nguồn có liên quan (hy vọng là từ thông số kỹ thuật) và bất kỳ "kỳ quặc" đáng chú ý nào của trình duyệt, nếu có.
dùng2864740

Câu trả lời:


116

Các ECMAScript 5.1 tiêu chuẩn phần 12.6.4 (trên cho trong vòng) cho biết:

Các thuộc tính của đối tượng được liệt kê có thể bị xóa trong quá trình liệt kê. Nếu một thuộc tính chưa được truy cập trong quá trình liệt kê bị xóa, thì nó sẽ không được truy cập. Nếu các thuộc tính mới được thêm vào đối tượng đang được liệt kê trong quá trình liệt kê, các thuộc tính mới được thêm vào sẽ không được đảm bảo sẽ được truy cập trong kiểu liệt kê đang hoạt động. Tên tài sản không được truy cập nhiều hơn một lần trong bất kỳ bảng liệt kê nào.

Vì vậy, tôi nghĩ rõ ràng rằng mã của OP là hợp pháp và sẽ hoạt động như mong đợi. Các câu hỏi kỳ quặc của trình duyệt ảnh hưởng đến thứ tự lặp lại và câu lệnh xóa nói chung, nhưng không ảnh hưởng đến việc mã OP có hoạt động hay không. Nói chung, tốt nhất chỉ nên xóa thuộc tính hiện tại trong lần lặp - việc xóa các thuộc tính khác trong đối tượng sẽ khiến chúng không được bao gồm (nếu đã được truy cập) hoặc không được đưa vào lần lặp, mặc dù điều đó có thể có hoặc không phải là mối quan tâm tùy thuộc vào tình hình.

Xem thêm:

Tuy nhiên, không có điều nào thực sự ảnh hưởng đến mã của OP.


1
Tôi chỉ nhận thấy rằng tôi đã bao gồm các trích dẫn tiêu chuẩn tương tự như câu trả lời khác, xin lỗi.
TomW

17

Từ đặc tả Javascript / ECMAScript (cụ thể là 12.6.4 Câu lệnh bổ sung ):

Các thuộc tính của đối tượng được liệt kê có thể bị xóa trong quá trình liệt kê . Nếu một thuộc tính chưa được truy cập trong quá trình liệt kê bị xóa, thì nó sẽ không được truy cập. Nếu các thuộc tính mới được thêm vào đối tượng đang được liệt kê trong quá trình liệt kê, các thuộc tính mới được thêm vào sẽ không được đảm bảo sẽ được truy cập trong kiểu liệt kê đang hoạt động . Tên tài sản không được truy cập nhiều hơn một lần trong bất kỳ bảng liệt kê nào.

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.