咱们能够发现 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
效率的确高不少