咱們能夠發現 for in
在vscode的代碼片斷是這樣的:數組
for (const key in object) { if (object.hasOwnProperty(key)) { const element = object[key]; } }
os: 用for in 循環的時候是要有這個判斷,vscode真嚴謹,真🐂🍺
可是爲何要有hasOwnProperty的這一層判斷呢?
不少人都會脫口而出:由於會循環這個對象的全部屬性影響效率app
let obj = {mood: 'happy'}; for(let key in obj){ console.log(key)//mood } //能夠看到並無打印出obj對象原型鏈上的那些屬性: constructor、isPrototypeOf、toString、propertyIsEnumerable等
os: 貌似根本用不到hasOwnProterty這一層判斷啊
Object.prototype.level=666 for(let key in obj){ console.log(key)//mood、level } Object.keys(obj)//["mood"]
Object.defineProperties(Object.prototype,{ isSuper: { value: true, enumerable: true }, isNormal: { value: true, enumerable: false } }); Object.defineProperties(obj,{ color:{ value: 'yellow', enumerable: true }, num: { value: 2, enumerable: false } }); for(let key in obj){ console.log(key)//mood、color、level、isSuper } Object.keys(obj)//["mood", "color"]
for...in
語句以任意順序遍歷一個對象的除
Symbol之外的
可枚舉屬性。循環將遍歷對象自己的全部可枚舉屬性,以及對象從其構造函數原型中繼承的屬性(就是原型鏈上)
一、這裏的‘任意順序’實際上是(從自身對象遍歷到原型鏈)這樣的順序。性能
二、constructor、isPrototypeOf、toString、propertyIsEnumerable
這些Object
原型對象上的屬性默認是不可枚舉的因此for in
循環不出來:spa
Object.getOwnPropertyDescriptor(Object.prototype, 'toString') //查看toString這個屬性的描述 {value:ƒ,writable:true,enumerable:false,configurable:true}
三、Object.keys()
方法會返回一個由一個給定對象的自身可枚舉屬性組成的數組,數組中屬性名的排列順序和使用for...in
循環遍歷該對象時返回的順序一致prototype
Object.keys
: 對象自身可枚舉的屬性Object.getOwnPropertyNames
: 對象自身屬性for in
: 循環對象包括原型鏈上可枚舉屬性hasOwnProperty()
: 判斷對象自身是否有這個屬性code
for in
+ hasOwnProperty
就是循環遍歷一個對象的自身可枚舉鍵 => Object.keys()for in
的性能let arr = [], n = 10000 for (let index = 0; index < n; index++) { arr.push(index) } function forin() { let temp = [] console.time(`for_in(${n}):`) for (const key in arr) { temp.push(arr[key]) } console.timeEnd(`for_in(${n}):`) } function forinOwn() { let temp = [] console.time(`for_in_own(${n}):`) for (const key in arr) { if (arr.hasOwnProperty) { temp.push(arr[key]) } } console.timeEnd(`for_in_own(${n}):`) } function forof() { let temp = [] console.time(`for_of(${n}):`) for (const item of arr) { if (arr.hasOwnProperty) { temp.push(item) } } console.timeEnd(`for_of(${n}):`) } console.log('數組長度:' + n) forin() forinOwn() forof()
數組長度:10000
for_in(10000):: 2.251ms
for_in_own(10000):: 4.474ms
for_of(10000):: 2.246msorm
數組長度:1000000
for_in(1000000):: 187.626ms
for_in_own(1000000):: 254.605ms
for_of(1000000):: 65.449ms對象
數組長度:10000000
for_in(10000000):: 2588.375ms
for_in_own(10000000):: 2500.013ms
for_of(10000000):: 1025.442ms繼承
1億就炸了。。
JavaScript heap out of memory <--- Last few GCs ---> [53665:0x104000000] 1966 ms: Mark-sweep 577.3 (585.0) -> 577.3 (582.0) MB, 64.3 / 0.0 ms (average mu = 0.459, current mu = 0.001) last resort GC in old space requested [53665:0x104000000] 2031 ms: Mark-sweep 577.3 (582.0) -> 577.3 (582.0) MB, 65.1 / 0.0 ms (average mu = 0.314, current mu = 0.000) last resort GC in old space requested
數組長度:20000000
for_in(20000000):: 6390.817ms
for_in_own(20000000):: 5915.073ms
for_of(20000000):: 979.788ms
for of
效率的確高不少