2013-07-27 15 views
92

Tôi được chuyển đến số for..in page của MDN khi nói, "for..in Lặp lại các thuộc tính đếm được của một đối tượng".Có nghĩa là gì?

Sau đó, tôi đã đi đến số Enumerability and ownership of properties page nơi thông báo "Thuộc tính có thể đếm được là những thuộc tính có thể được lặp lại bởi vòng lặp for..in".

Từ điển được định nghĩa là đếm được, nhưng tôi không thể hình dung được ý nghĩa của nó. Tôi có thể lấy một ví dụ về cái gì đó được liệt kê không?

+0

Bạn có hiểu những gì 'cho-in' không? –

+0

Từ các câu trả lời tôi nhận được for..in cho phép tất cả các thuộc tính enumerable của một đối tượng có sẵn để sử dụng với câu lệnh – Patrick

+5

Ý nghĩa đơn giản nhất là: liệu thuộc tính sẽ được tạo bởi vòng lặp 'for in' hay không (cho những người không muốn biết chi tiết hoặc không quan tâm;)) –

Trả lời

90

Thuộc tính có thể đếm được là thuộc tính có thể được đưa vào và truy cập trong vòng for..in vòng lặp (hoặc lặp lại các thuộc tính tương tự, như Object.keys()).

Nếu thuộc tính không được xác định là đếm được, vòng lặp sẽ bỏ qua nó nằm trong đối tượng.

var obj = { key: 'val' }; 

console.log('toString' in obj); // true 
console.log(typeof obj.toString); // "function" 

for (var key in obj) 
    console.log(key); // "key" 

Một tài sản được xác định là đếm được hay không bằng cách riêng [[Enumerable]] attribute của nó. Bạn có thể xem đây như một phần của property's descriptor:

var descriptor = Object.getOwnPropertyDescriptor({ bar: 1 }, 'bar'); 

console.log(descriptor.enumerable); // true 
console.log(descriptor.value);  // 1 

console.log(descriptor); 
// { value: 1, writable: true, enumerable: true, configurable: true } 

Một for..in vòng lặp sau đó lặp qua tên thuộc tính của đối tượng.

var foo = { bar: 1, baz: 2}; 

for (var prop in foo) 
    console.log(prop); // outputs 'bar' and 'baz' 

Nhưng, chỉ đánh giá tuyên bố của mình-console.log(prop); trong trường hợp này - đối với những thuộc tính mà [[Enumerable]] thuộc tính là true.

Tình trạng này được đặt ra bởi vì đối tượng have many more properties, đặc biệt là from inheritance:

console.log(Object.getOwnPropertyNames(Object.prototype)); 
// ["constructor", "toString", "toLocaleString", "valueOf", "hasOwnProperty", "isPrototypeOf", "propertyIsEnumerable", /* etc. */] 

Mỗi thuộc tính vẫn exists on the object:

console.log('constructor' in foo); // true 
console.log('toString' in foo); // true 
// etc. 

Tuy nhiên, họ đang bỏ qua (hoặc "không được tính ") bởi vòng lặp for..in vì chúng không thể đếm được.

var descriptor = Object.getOwnPropertyDescriptor(Object.prototype, 'constructor'); 

console.log(descriptor.enumerable); // false 
+0

Vì vậy, thuộc tính hàm tạo không được liệt kê vì nó không hiển thị trong vòng lặp for..in. Trong khi các tên của các thuộc tính như thanh hoặc baz là enumerable bởi vì bạn đã có thể console.log mỗi một từ đối tượng? – Patrick

34

Nếu bạn tạo đối tượng qua myObj = {foo: 'bar'} hoặc ở nơi nào đó, tất cả thuộc tính đều có thể đếm được. Vì vậy, câu hỏi dễ dàng hơn để hỏi là, những gì không phải là đếm? Một số đối tượng có một số thuộc tính không thể đếm được, ví dụ nếu bạn gọi Object.getOwnPropertyNames([]) (trả về một mảng thuộc tính, có thể đếm được hay không, trên []), nó sẽ trả về ['length'], bao gồm thuộc tính không thể đếm được của một mảng, ' chiều dài'.

Bạn có thể làm cho tính chất phi đếm được của riêng bạn bằng cách gọi Object.defineProperty:

var person = { age: 18 }; 
Object.defineProperty(person, 'name', { value: 'Joshua', enumerable: false }); 

person.name; // 'Joshua' 
for (prop in person) { 
    console.log(prop); 
}; // 'age' 

Ví dụ này vay mượn rất nhiều từ Non-enumerable properties in JavaScript, nhưng cho thấy một đối tượng được liệt kê trên. Thuộc tính có thể là hoặc không thể ghi, có thể định cấu hình hoặc đếm được. John Resig thảo luận về điều này trong phạm vi ECMAScript 5 Objects and Properties.

Và, có câu hỏi về Stack Overflow về why you'd ever want to make properties non-enumerable.

+0

Hm, cả upvotes và downvotes. Chắc chắn, nếu có bất cứ điều gì về câu trả lời này có giá trị downvoting, xin vui lòng thêm một bình luận ở đây. – carpeliam

+0

Một câu trả lời khác đã viết: var o = {}; o ['foo'] = 0; // enumerable, normal Object.defineProperty (o, 'bar', {value: 1}); // không thể đếm được, lạ Tại sao phải thêm một cách rõ ràng là có thể đếm được: sai? – Patrick

+5

@Patrick, tôi đã đưa nó vào một phần để rõ ràng từ ví dụ rằng đó là một lựa chọn, nhưng tùy thuộc vào khán giả của bạn, rõ ràng có thể là một quyết định vững chắc để mọi người đọc mã của bạn rõ ràng. – carpeliam

9

Nếu bạn gặp khó khăn trong việc hình dung "có nghĩa là gì để được liệt kê?" tại sao không tự hỏi mình, có nghĩa là gì không thể đếm được?

tôi nghĩ về nó một chút như thế này, một nonenumerable tài sản tồn tại nhưng là một phần hidden; có nghĩa là không thể đếm số là điều kỳ lạ. Bây giờ bạn có thể tưởng tượng được liệt kê như những gì còn lại - tài sản tự nhiên hơn mà chúng ta thường gặp phải vì chúng ta đã phát hiện ra Đối tượng. Cân nhắc

var o = {}; 
o['foo'] = 0;        // enumerable, normal 
Object.defineProperty(o, 'bar', {value: 1}); // nonenumerable, weird 

Bây giờ trong một for..in, tưởng tượng nó như giả

for property in o: 
    if not property enumerable continue // skip non-enumerable, "bar" 
    else do /* whatever */    // act upon enumerable, "foo" 

nơi cơ thể của vòng lặp bạn gõ vào Javascript là ở nơi /* whatever */

18

Đó là rất nhiều nhàm chán hơn cái gì đó nên được hình dung.

Có nghĩa đen là thuộc tính trên tất cả các thuộc tính được gọi là "đếm được". Khi được đặt thành false, phương thức for..in sẽ bỏ qua thuộc tính đó, giả sử nó không tồn tại.

Có rất nhiều thuộc tính trên các đối tượng có "liệt kê" được đặt thành false, như "valueOf" và "hasOwnProperty", vì nó được cho là bạn không muốn công cụ JavaScript lặp lại trên các đối tượng đó.

Bạn có thể tạo các thuộc tính không đếm được của riêng bạn bằng cách sử dụng phương pháp Object.defineProperty:

var car = { 
    make: 'Honda', 
    model: 'Civic', 
    year: '2008', 
    condition: 'bad', 
    mileage: 36000 
    }; 

    Object.defineProperty(car, 'mySecretAboutTheCar', { 
    value: 'cat pee in back seat', 
    enumerable: false 
    }); 

Bây giờ, thực tế là có thậm chí là một bí mật về chiếc xe là ẩn. Tất nhiên họ vẫn có thể truy cập vào bất động sản trực tiếp và nhận được câu trả lời:

console.log(car.mySecretAboutTheCar); // prints 'cat pee in back seat' 

Tuy nhiên, họ sẽ phải biết rằng tài sản tồn tại đầu tiên, bởi vì nếu họ đang cố gắng để truy cập nó thông qua for..in hoặc Object.keys nó sẽ vẫn hoàn toàn bí mật:

console.log(Object.keys(car)); //prints ['make', 'model', 'year', 'condition', 'mileage'] 

Họ nên gọi nó là "forInAble".

+2

Upvoted cho rằng dòng cuối cùng - Tôi nghĩ rằng nếu nó thực sự đã được gọi là forInAble không ai sẽ được hỏi về nó cả. Điều này sẽ trả lời câu hỏi của tôi - tại sao bạn phải (hoặc tại sao bạn phải) thiết lập một tài sản không được liệt kê? Thuộc tính length của một mảng được sử dụng khá thường xuyên như một ví dụ về một thuộc tính không thể đếm được, nhưng tại sao bạn không thể đặt nó thành enumerable (không phải là hạn chế JavaScript, ý tôi là, tại sao nó được đặt thành không đếm được trong JavaScript trong nơi đầu tiên)? – Chris

+0

Để làm rõ câu hỏi của tôi, tại sao nó đã quyết định rằng những điều sau đây không phải là một lựa chọn: thực hiện: Honda mô hình: Civic bí mật: Cát Pee ** Chiều dài: 12 ** – Chris

+0

Hmmm ... Tôi có thể tìm thấy câu trả lời cho câu hỏi của tôi. Từ tìm kiếm trên google cho "Bạn có ý nghĩa gì với các loại dữ liệu được liệt kê?" Dữ liệu được liệt kê có tập hợp các giá trị hữu hạn. Loại dữ liệu được liệt kê bao gồm các giá trị mà bạn cho phép cho loại đó hoặc các giá trị được liệt kê. Đối với các kiểu liệt kê số nguyên, mỗi giá trị được liệt kê bao gồm tên và giá trị số cơ bản. Do đó, nếu tôi hiểu chính xác, vì có vô số độ dài có thể, bạn sẽ phải gán một số lượng vô hạn tên, một tên cho mỗi chiều dài. Đúng không? – Chris

0

phương pháp không được liệt kê; hoặc được xây dựng trong phương pháp không phải là .. tho sau khi tìm kiếm trên những gì enumerable có nghĩa là để java script; nó chỉ đề cập đến thuộc tính property .. tất cả các đối tượng được tạo trong ecma3 đều có thể đếm được, và ecma5 u bây giờ có thể định nghĩa nó .... đó là nó ..: D lol đưa tôi một chút để tìm câu trả lời; nhưng tôi tin rằng nó được nói đến trong cuốn sách của David Flanagan .. vì vậy tôi đoán nó có nghĩa là "ẩn", hoặc không "ẩn" trong các phương pháp đó không được hiển thị trong vòng lặp, và do đó "ẩn"

2

Tôi sẽ viết một định nghĩa dòng của ENUMERABLE

Có thể đếm được: Chỉ định xem thuộc tính có thể được trả về trong vòng lặp for/in hay không.

var obj = {}; 
Object.defineProperties(data, { 
    set1: {enumerable: true}, 
    set2: {enumerable: false}, 
}); 
Object.keys(obj); // ["set1"] 
Object.getOwnPropertyNames(obj); // ["set1", "set2"]