學(xué)網(wǎng)站建設(shè) 去哪里百度推廣客戶端下載安裝
for in
如果讓你遍歷對象中的key和value,你第一個想到的一定是使用for in
const o={name:"chengqige",age:23
}
for (let key in o){console.log(key,o[key]);
}

看起來是沒有問題的,但是如果我在下面加一行代碼,輸出的結(jié)果就可能讓你覺得奇怪了
const o = {name: "chengqige",age: 23
}
Object.prototype.getName = function () {}
Object.prototype.test = 12
for (let key in o) {console.log(key, o[key]);
}

你會發(fā)現(xiàn)for in多打印出了兩行東西,它們分別是Object原型上的方法和屬性getName
和test
,那么這個是為什么呢?
因為for in會打印原型上的所有可以被枚舉的方法
什么是可枚舉?
在JS中我們給一個對象添加屬性一共有三種辦法:
1.通過點語法直接添加屬性
const o={}
o.a=1
for(let key in o){console.log(key)
}
輸出結(jié)果:a
2.通過動態(tài)索引添加
什么是動態(tài)索引?我們普遍認(rèn)為一個對象的key是寫死的,value是變量,key不可編程,value可以被賦值
// 變量
const value=12
const o={"寫死的":value
}
但是實際上我們的 key也是可以用變量控制的,請看下面的例子
const value=12
const key ="動態(tài)索引"
const o={[key]:value
}
我們使用[]來擴起來變量,表示這個屬性是動態(tài)的,是有外部變量控制的
3.通過API添加
es6新增一個API可以直接為對象添加屬性
const o = {"b": 12
}
Object.defineProperty(o, "a", {get() {return 1}
})
for (let key in o) {console.log(key);
}
console.log("i am here", o.a)
但是它的輸出結(jié)果是:
問題出現(xiàn)了,為什么for in沒有出這個屬性a,但是我們使用o.a可以打印出來它
因為for in只能遍歷可以被枚舉的屬性,我們改造一下代碼,讓我們新添加的a是可以被枚舉的就好了
Object.defineProperty(o, "a", {get() {return 1},// +新增enumerable: true
})
這一次我們發(fā)現(xiàn)for in打印的結(jié)果就有a了
什么是原型
原型是與生俱來固有的對象,原型里有很多開箱即用的方法,因此在創(chuàng)建某些對象的同時,這個方法就可以被使用了。
比如數(shù)組中的push、pop、shift、unshift
任何數(shù)組都可以用它們,難道不是嘛
var arr = []
arr.push(1,2,3,4)
// [1,2,3,4]
那么這些原型上的方法是官方的,所以它們是不可以被枚舉的,那么用for…in遍歷它是沒有的
// 這個點語法創(chuàng)造的天生可以被枚舉,動態(tài)索引也是
Array.prototype.mine = function(){}
for (let key in Array.prototype){console.log(key,'只有可以枚舉的才會出現(xiàn)哦')
}

如果你在瀏覽器環(huán)境下運行這個代碼:
<script>Array.prototype.mine = function () { }console.log(Array.prototype);for (let key in Array.prototype){console.log(key,'只有可以枚舉的才會出現(xiàn)哦')}
</script>

深色的表示這些屬性是可以被枚舉的,淺色的表示這些屬性是不可被枚舉的,谷歌瀏覽器用顏色深淺來劃分
那么我們可以不可以讓這些不可枚舉的方法設(shè)置成可枚舉的呢?當(dāng)然可以!
Array.prototype.mine = function () { }
Object.defineProperty(Array.prototype, "push", {get(){return 1},enumerable: true})console.log(Array.prototype);for (let key in Array.prototype) {console.log(key, '只有可以枚舉的才會出現(xiàn)哦')}let arr=[]arr.push(1,3)console.log(arr);

總結(jié)
for … in不是一個很好的方法,它會把原型鏈上所有可枚舉的方法打印
Object.prototype.mine = function () { }
Array.prototype.okkk = function () { }
let arr = [1, 2, 3]
for (let key in arr) {console.log(key)
}
const o = {name: "chengqige",age: 23
}
Object.prototype.getName = function () {}
Object.prototype.test = 12
for (let key in o) {console.log(key, o[key]);
}

替代方案
Object.keys(o).forEach()
const o = {name: "chengqige",age: 23
}
Object.prototype.getName = function () {}
Object.prototype.test = 12
Object.keys(o).forEach(key=>{console.log(key, o[key]);
})
for in
+hasOwnProperty
const o = {name: "chengqige",age: 23
}
Object.prototype.getName = function () {}
Object.prototype.test = 12
for (let key in o) {if(o.hasOwnProperty(key)){console.log(key, o[key]);}
}
上面兩種的輸出結(jié)果都是