ES6用于获取原型值 - 如何检查hasownproperty

时间:2015-11-05 20:14:31

标签: javascript ecmascript-6

使用for...in我总是检查hasOwnProperty(我猜这是使用Object.keys的好参数),如:

for (let a in obj) {
    if (obj.hasOwnProperty(a)) {
        //logic
    }
}

我在使用for...of时是否需要进行相同的检查?如果是,我应该怎么做?

根据MDN page on for...of

  

for...in遍历属性名称时,for...of会迭代属性值

但它没有说明该迭代是包含继承属性还是仅包含实例属性。那里给出的解释和示例代码只涉及实例属性。

2 个答案:

答案 0 :(得分:17)

for...of遍历可迭代对象的迭代器。在ES6规范中,由Symbol.iterator属性在对象上标识为对象生成迭代器的函数;即,someObj[Symbol.iterator]

Symbol.iterator为每个可迭代类型返回的迭代器是不同的,但一般来说它只会迭代对象包含的相对于类型有意义的值。例如:

向对象的原型添加属性不太可能影响迭代器的行为,因此在这方面不是必需来测试值是否来自自己的属性。

Mapfor..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。最好的办法是在要部署的环境中尝试它。