3 回答

TA貢獻1735條經驗 獲得超5個贊
可枚舉的屬性是可以在for..in循環(或類似的屬性迭代,如Object.keys())中包含和訪問的屬性。
如果某個屬性未被標識為可枚舉,則循環將忽略該屬性在對象內。
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"
屬性通過其自己的[[Enumerable]]屬性被標識為可枚舉或不可枚舉。您可以將其視為屬性描述符的一部分:
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 }
一for..in則遍歷對象的屬性名稱進行迭代。
var foo = { bar: 1, baz: 2};
for (var prop in foo)
console.log(prop); // outputs 'bar' and 'baz'
但是,console.log(prop);在這種情況下,僅對[[Enumerable]]屬性為的那些屬性評估其語句true。
之所以存在此條件,是因為對象具有更多的屬性,尤其是繼承的屬性:
console.log(Object.getOwnPropertyNames(Object.prototype));
// ["constructor", "toString", "toLocaleString", "valueOf", "hasOwnProperty", "isPrototypeOf", "propertyIsEnumerable", /* etc. */]
這些屬性中的每一個仍然存在于對象上:
console.log('constructor' in foo); // true
console.log('toString' in foo); // true
// etc.
但是,for..in由于它們無法枚舉,因此被循環跳過了。
var descriptor = Object.getOwnPropertyDescriptor(Object.prototype, 'constructor');
console.log(descriptor.enumerable); // false

TA貢獻1834條經驗 獲得超8個贊
這比應該可視化的東西要無聊得多。
實際上,所有屬性上都有一個稱為“可枚舉”的屬性。如果將其設置為false,則該for..in方法將跳過該屬性,并假裝該屬性不存在。
對象上有很多屬性都將“可枚舉”設置為false,例如“ valueOf”和“ hasOwnProperty”,因為假定您不希望JavaScript引擎在這些屬性上進行迭代。
您可以使用以下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
});
現在,關于汽車的秘密這個事實已經隱藏了。當然,他們仍然可以直接訪問該屬性并獲得答案:
console.log(car.mySecretAboutTheCar); // prints 'cat pee in back seat'
但是,他們必須知道該屬性首先存在,因為如果他們試圖通過它進行訪問,for..in否則Object.keys它將完全是秘密的:
console.log(Object.keys(car)); //prints ['make', 'model', 'year', 'condition', 'mileage']
他們應該將其稱為“ forInAble”。
添加回答
舉報