for in
可以遍历对象,除了常规的使用外还需要注意:
除了可以遍历对象本身的属性外,还可以遍历到对象的继承属性,看一段代码
let obj = {name:"zhang"}
我们在这里定义了一个对象obj,然后我们使用for in来遍历它
for(let key in obj){
console.log(key) // name
}
这里遍历后,我们可以看到打印了name,这个没有什么争议,那现在我们再定一个对象,然后让obj的原型继承到这个新对象试一下
let parent = {sex: "women"}
Object.setPrototypeOf(obj, parent)
现在obj继承了parent了,我们看看它上面的sex属性是否能被遍历到
for(let key in obj){
console.log(key) // name sex
}
遍历后我们看到打印了name和sex,所以要记住哈,for in不止遍历自己的属性还能遍历到继承对象中的属性
那如果我们再改造一下这个parent对象,将这个sex属性的描述改造一下呢,我们先来看看默认情况下的sex描述吧
Object.getOwnPropertyDescriptor(parent, 'sex')
然后,我们之后会得到一个描述的对象
{
value: ‘women’, // 属性对应的值
writable: true, // 属性时候可以修改
enumerable: true, // 属性时候可以遍历(是否可以枚举)
configurable: true // 属性时候可以删除
}
我们现在来重新定义一下这个属性吧
Object.defineProperty(parent, 'sex', {
value: 'women',
writable: true,
enumerable: false, // 这里用false,让它不可以被遍历(就是不可枚举)
configurable: true
})
我们再次重新让obj继承改造后的parent
Object.setPrototypeOf(obj, parent)
再次遍历
for(let key in obj){
console.log(key) // 只有name了…
}
最终有了结论: for in 除了可以遍历自己的属性外,还可以遍历继承对象中可枚举的属性.
Object.keys
我们接着上面的代码,我们再来看看这个能遍历出个啥呢
Object.keys(obj). // name
obj上面的继承的不可枚举的sex遍历不到,那我们再把sex改成可枚举的再试试吧
Object.defineProperty(parent, 'sex', {
value: 'women',
writable: true,
enumerable: true, // 改成可枚举
configurable: true
})
Object.setPrototypeOf(obj, parent)
现在obj继承了parent,并且其中的sex可枚举了…
再来重新遍历试试吧
Object.keys(obj)。// 还是只有name啊...
有了结论: Object.keys它只能遍历自己对象中的属性.
我们除了知道对象属性的遍历规则外,还需要知道一下下面:
对象中属性被遍历的顺序
我们来定义一个对象,对象属性包含三种类型的,分别为:数值、字符串、Symbol
let obj = {
2: "zhang",
0: 18,
1: true,
"ok": "ok",
"": "beauty",
[Symbol()]:0
}
我们来打印这个obj
{
0: 18,
1: true,
2: ‘zhang’,
ok: ‘ok’,
“”: ‘beauty’,
Symbol(): 0
}
我们再来遍历一下obj,看看属性的顺序吧…
先来看看for in
for(let key in obj){
console.log(key)。// 0 1 2 ‘ok’ ‘’ 没有Symbol哦
}
我们看到for in遍历的顺序同打印出的obj的属性顺序,但是得不到Symbol的,再来看Object.keys
Object.keys(obj)。 // ['0', '1', '2', 'ok', ''] 也得不到Symbol哦
可以看到object.keys遍历的顺序也是同obj打印的相同,同时也和for in一样得不到Symbol
这样我们就有了结论: 对象中定义的属性,是按照这样的规则定
义顺序的
1、先找数值类型: 按照数字的值升序排列
2、再找字符串类型: 按照定义的顺序升序排列
3、最后找Symbol类型,按照定义的顺序升序排列