1、结论
for in遍历对象所有可枚举属性 包括原型链上的属性
Object.keys遍历对象所有可枚举属性 不包括原型链上的属性
hasOwnProperty 检查对象是否包含属性名,无法检查原型链上是否具有此属性名
2、示例代码
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>for in 与 Object.keys 与 hasOwnProperty区别</title>
</head>
<body>
<script type="text/javascript">
var aa = [12, 34, 5];
Array.prototype.add = function() {}
for(let i in aa) {
console.log(i);
//输出0 1 2 add
}
console.log('--------------')
console.log(Object.keys(aa));
//输出0 1 2
console.log(aa.hasOwnProperty('add'))
//输出false
console.log(aa.hasOwnProperty('0'))
//输出true
</script>
</body>
</html>
3、ESLINT对for in的限制
当你在某个对象上用 for in 语句遍历对象属性,而又忘了用 hasOwnProperty 判断属性来源的时候,你就会发现被你扩展的原型属性也会被遍历出来,这往往都不是我们想要的结果。
总的来说,操作中引入继承的属性会让问题复杂化,大多数时候,我们只关心对象自身的属性。所以,尽量不要用for...in
循环,而用Object.keys()
代替。
ES2017 引入了跟Object.keys
配套的Object.values
和Object.entries
,作为遍历一个对象的补充手段,供for...of
循环使用。
let {keys, values, entries} = Object;
let obj = { a: 1, b: 2, c: 3 };
for (let key of keys(obj)) {
console.log(key); // 'a', 'b', 'c'
}
for (let value of values(obj)) {
console.log(value); // 1, 2, 3
}
for (let [key, value] of entries(obj)) {
console.log([key, value]); // ['a', 1], ['b', 2], ['c', 3]
}