使用for...in
我总是检查hasOwnProperty
(我猜这是使用Object.keys
的好参数),如:
for (let a in obj) {
if (obj.hasOwnProperty(a)) {
//logic
}
}
我在使用for...of
时是否需要进行相同的检查?如果是,我应该怎么做?
当
for...in
遍历属性名称时,for...of
会迭代属性值
但它没有说明该迭代是包含继承属性还是仅包含实例属性。那里给出的解释和示例代码只涉及实例属性。
答案 0 :(得分:17)
for...of
遍历可迭代对象的迭代器。在ES6规范中,由Symbol.iterator
属性在对象上标识为对象生成迭代器的函数;即,someObj[Symbol.iterator]
。
Symbol.iterator
为每个可迭代类型返回的迭代器是不同的,但一般来说它只会迭代对象包含的相对于类型有意义的值。例如:
String
iterator将每个代码点迭代为单字符字符串Map
iterator遍历[[MapData]]
的{{1}}内部广告位,这是存储键值映射的位置Array
iterator仅迭代整数索引(请参阅%ArrayIteratorPrototype%.next
)向对象的原型添加属性不太可能影响迭代器的行为,因此在这方面不是必需来测试值是否来自自己的属性。
Map
和for..of
根本不同。 for..in
遍历对象的属性,有时需要询问有关这些属性的问题,例如它们是否是继承的。 for..in
将值从迭代器中抽出,迭代器私下决定以什么顺序返回哪些值。询问for..of
迭代的结果是否来自继承属性并不一定有意义,因为它可能根本不是来自属性。 (例如,for..of
的{{1}}迭代返回未作为属性公开的值。)
如果所有以下条件都成立,我只能想到一个(极其奇怪的)情况,其中继承的属性会影响for..of
迭代器的行为:
Map
具有带整数名称的属性,并且Array
大于整数索引的名称例如:
Array.prototype
在这个非常奇怪的情况下,您将遍历继承的length
属性。但这确实是我能想到的唯一一个案例;其他继承的属性将被忽略,因为它们没有整数名称,或者因为它们被具有相同整数名称的实例属性遮蔽,或者因为它们大于或等于实例的Array.prototype["7"] = "hello"; // why are you doing this?? :O
var a = [1,2,3]
a.length = 8; // why are you doing this?? D:
for(g of a) { console.log(g); } // great job, you got strange results
。
答案 1 :(得分:0)
您无法真正执行相同的检查,因为您无法明确访问该属性密钥。
var arr = [1, 2, 3];
for(let val of arr) {
// all you have is the value
// there is no way to check
console.log(val);
}
for-of
语句可以与任何iterable object一起使用,并且定义可迭代协议的方式因对象而异。
使用hasOwnProperty
检查的原因是确保属性在对象上,而不是在对象的原型上。您可以轻松地测试for-of
是否相同。
var prototype = { a: 1 };
var instance = Object.create(prototype);
instance.b = 2;
instance.c = 3;
for(var val of instance) {
console.log(val);
}
目前,不同的环境有for-of
的不同实现,它在我的浏览器中使用Arrays,但不适用于Objects。最好的办法是在要部署的环境中尝试它。