当它说“for..in 迭代对象的可枚举属性”时,我被定向到 MDN 的for..in 页面。
然后我转到属性的可枚举性和所有权页面,它说“可枚举属性是那些可以通过 for..in 循环迭代的属性”。
字典将 enumerable 定义为可数,但我无法想象这意味着什么。我能得到一个可枚举的例子吗?
当它说“for..in 迭代对象的可枚举属性”时,我被定向到 MDN 的for..in 页面。
然后我转到属性的可枚举性和所有权页面,它说“可枚举属性是那些可以通过 for..in 循环迭代的属性”。
字典将 enumerable 定义为可数,但我无法想象这意味着什么。我能得到一个可枚举的例子吗?
可枚举属性是可以在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
如果您通过myObj = {foo: 'bar'}
或其他方式创建对象,则所有属性都是可枚举的。所以更容易问的问题是,什么是不可枚举的?某些对象具有一些不可枚举的属性,例如,如果您调用Object.getOwnPropertyNames([])
(它返回一个包含所有属性的数组,无论是否可枚举,在 [] 上),它将返回['length']
,其中包括数组的不可枚举属性 'length' .
您可以通过调用来创建自己的不可枚举属性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'
这个例子大量借鉴了 JavaScript 中的不可枚举属性,但显示了一个被枚举的对象。属性可以是或不可写的、可配置的或可枚举的。John Resig 在ECMAScript 5 对象和属性的范围内讨论了这一点。
并且,有一个 Stack Overflow 问题,关于为什么您想要使属性不可枚举。
它比应该可视化的东西要无聊得多。
从字面上看,所有属性上都有一个称为“可枚举”的属性。当它设置为 false 时,该for..in
方法将跳过该属性,假装它不存在。
将“enumerable”设置为 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”。
我将编写ENUMERABLE 的一行定义
Enumerable
:指定是否可以在 for/in 循环中返回该属性。
var obj = {};
Object.defineProperties(obj, {
set1: {enumerable: true},
set2: {enumerable: false},
});
Object.keys(obj); // ["set1"]
Object.getOwnPropertyNames(obj); // ["set1", "set2"]
如果您很难想象“可枚举意味着什么?” 为什么不问问自己,不可枚举是什么意思?
我觉得有点像这样,一个不可枚举的属性存在但部分隐藏;这意味着不可枚举是奇怪的。现在您可以将 enumerable 想象为剩下的东西——自从我们发现Objects以来,我们习惯遇到的更自然的属性。考虑
var o = {};
o['foo'] = 0; // enumerable, normal
Object.defineProperty(o, 'bar', {value: 1}); // nonenumerable, weird
现在在 a 中for..in
,把它想象成伪代码
for property in o:
if not property enumerable continue // skip non-enumerable, "bar"
else do /* whatever */ // act upon enumerable, "foo"
您在JavaScript中键入的循环主体所在的位置/* whatever */