2012-01-08 33 views
6

Tôi muốn loại bỏ một số thành viên của một đối tượng (vì lợi ích của đối số, những người có khóa bắt đầu bằng '_'). Một cách thanh lịch để làm điều này là gì? Cách ngây thơ sẽ là:Thành ngữ tốt để lọc ra các thành viên của một đối tượng (javascript)

for (var i in obj) 
    if (i[0] === '_') 
    delete obj[i]; 

nhưng điều đó sửa đổi đối tượng bên dưới trong khi lặp lại. Trong Node ít nhất tôi đoán tôi có thể

Object.keys(obj).forEach(function (i) { if (i[0] === '_') delete obj[i]; }); 

hoặc khởi động lại lần lặp mỗi khi có gì đó bị xóa với vòng lặp lồng nhau khó xử.

Có giải pháp nào tốt hơn không?

EDIT: Trong thử nghiệm ngay bây giờ, trong node.js ít nhất, giải pháp ngây thơ thực sự có vẻ hoạt động. Nó chắc chắn là có thể cho ... trong là (bắt buộc phải được) thực hiện một cách an toàn. Có ai biết không?

+3

Việc sửa đổi đối tượng trong vòng lặp 'for ... in' có gây ra sự cố không? Tôi không thấy nó khác nhiều so với việc sửa đổi đối tượng trong hàm gọi lại 'forEach()'. – Pointy

+0

Tôi giả sử rằng 'Object.keys' chụp nhanh các phím trong đối tượng. Có lẽ điều đó không đúng. – Grumdrig

+0

... và giả sử rằng 'for (... in ...)' không chụp nhanh đối tượng. – Grumdrig

Trả lời

17

Bạn không cần phải lo lắng về điều đó. Một đoạn trích cho ECMAScript Language Specification §12.6.4 rõ ràng Kỳ (nhấn mạnh của tôi):

Các cơ và trật tự của liệt kê các thuộc tính (bước 6.a trong thuật toán đầu tiên, bước 7.A trong lần thứ hai) là không được chỉ định. 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 thời gian điều tra sẽ bị xóa, thì nó sẽ không được truy cập. Nếu mới thuộc tính được thêm vào đối tượng được liệt kê trong khi đếm , các thuộc tính mới được thêm không được đảm bảo là được truy cập trong liệt kê hoạt động. Không được truy cập tên thuộc tính nhiều lần trong bất kỳ điều tra nào.

+0

-1 - "Nếu một tài sản chưa được truy cập trong quá trình liệt kê" - tôi nghĩ đó không phải là trường hợp ở đây. – thejh

+0

@thejh, sau đó áp dụng cho trước. 'for..in' hoàn toàn an toàn cho việc xóa thuộc tính theo tiêu chuẩn. – OnTheFly

+1

+1 câu trả lời hay với phần tóm tắt hoàn toàn không có thật –

4

tại sao không tạo ra một danh sách những cái tên để loại bỏ như

var l = []; 
for (var i in obj) 
    if (i[0] === '_') 
    l.push(i); 
l.forEach(function(v){ delete obj[v]; }); 
4
Object.keys(obj).filter(function (v) { 
    return v[0] === "_"; 
}).forEach(function (v) { 
    delete obj[v]; 
}); 

này sẽ sửa đổi các đối tượng trong một vòng lặp dù; p

Nếu bạn sử dụng này nhiều lần các generic là :

Object.keys(obj).filter(function (v) { 
    //filter the object values/keys by some conditions 
}).forEach(del.bind(obj)); 

function del (v) { 
    delete this[v]; 
} 
+0

Cảm ơn. Không biết về 'bộ lọc'. – Grumdrig

2

Cách khác là tạo hàm trả về đối tượng đã lọc. Tôi thích giải pháp này để tránh các tác động đối với các phần khác của mã giữ một tham chiếu đến đối tượng đang được sửa đổi.

function filterObject(obj) { 
    var filtered = new Object(); 
    for (var i in obj) 
    if (i[0] != '_') 
     filtered[i] = obj[i]; 
    return filtered; 
} 
Các vấn đề liên quan