引子:
我们可以发现 for in
在vscode的代码片段是这样的:
for (const key in object) {
if (object.hasOwnProperty(key)) {
const element = object[key];
}
}
os: 用for in 循环的时候是要有这个判断,vscode真严谨,真🐂🍺
但是为什么要有hasOwnProperty的这一层判断呢?
很多人都会脱口而出:因为会循环这个对象的所有属性影响效率
实验一:
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以外的可枚举属性。循环将遍历对象本身的所有可枚举属性,以及对象从其构造函数原型中继承的属性(就是原型链上)
1、这里的‘任意顺序’其实是(从自身对象遍历到原型链)这样的顺序。
2、constructor、isPrototypeOf、toString、propertyIsEnumerable
这些Object
原型对象上的属性默认是不可枚举的所以for in
循环不出来:
Object.getOwnPropertyDescriptor(Object.prototype, 'toString')
//查看toString这个属性的描述
{value:ƒ,writable:true,enumerable:false,configurable:true}
3、Object.keys()
方法会返回一个由一个给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和使用for...in
循环遍历该对象时返回的顺序一致
结论:
Object.keys
: 对象自身可枚举的属性Object.getOwnPropertyNames
: 对象自身属性for in
: 循环对象包括原型链上可枚举属性hasOwnProperty()
: 判断对象自身是否有这个属性
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.246ms
数组长度: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
效率的确高很多
测试公式: $$x*y=z$$
测试公式: $2^32$ 内联???
test
- 比如今年我们与 Arm 中国建立了战略合作,通过我们的能力协助 Arm 中国一起构建了 AIoT 的开发者社区——极术社区。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。