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]
}