当前位置:网站首页>请讲一讲JS中的 for...in 与 for...of (上)

请讲一讲JS中的 for...in 与 for...of (上)

2022-08-09 22:01:00 lazytomato

start

  • 前几天睡觉老梦到去面试,面试官让我说说for...infor...of的区别。
  • 一次两次也就罢了,关键是一直梦到,而且更关键的是我还说不明白。
  • 现在学还来得及嘛?手动狗头

for…in

先看看MDN 的说明吧

解释:
for…in 语句以任意顺序迭代一个对象的除 Symbol 以外的可枚举属性,包括继承的可枚举属性。

思考:

  1. 任意顺序迭代
    迭代的顺序是任意的,所以 MDN 后续文档又这么一句话 备注:for...in不应该用于迭代一个关注索引顺序的 Array。

  2. 除 Symbol 以外的可枚举属性
    所以需要注意下,for…in 无法遍历 Symbol 类型的属性;

  3. 可枚举属性
    是否可枚举,可以通过Object.defineProperty()属性enumerable定义(默认 enumerable 为 false);
    快速判断属性是否可枚举可通过 Object.prototype.propertyIsEnumerable()

  4. 包括继承的可枚举属性
    原型链上的可枚举属性也会被遍历到。

验证一下:
1.验证第一条 ”任意顺序迭代“

/* 我这里将属性值不为number类型的放在靠前的位置 */
var obj = {
    
  4: 'string',
  5: false,
  6: function () {
    
    console.log(1)
  },
  1: 1,
  2: 2,
  3: 3,
}

for (const key in obj) {
    
  console.log(key, obj[key])
}

/* 1 1 2 2 3 3 4 string 5 false 6 [Function: 6] */

// for...in 遍历对象是按什么顺序遍历的? 有这么一个评论,仅供**参考**
// ES6 之前 Object 的键值对是无序的,所以遍历也无序可言。ES6 之后 Object 的键值对按照自然数、非自然数和 Symbol 进行排序,自然数是按照大小升序进行排序,其他两种都是按照插入的时间顺序进行排序。

2.验证第二条 “除 Symbol 以外的可枚举属性”

var obj = {
    
  1: 11,
  [Symbol('tomato')]: 'lazy', // 属性名直接写 Symbol表达式会报错,所以这里我用了中括号包裹一下。
  name: '测试symbol',
}

for (const key in obj) {
    
  console.log(key, obj[key])
}
/* 1 11 name 测试symbol */

3.验证第三条 “可枚举属性”

var obj = {
    
  name: '测试可枚举属性',
}

for (const key in obj) {
    
  console.log(key, obj[key])
}
/* name 测试可枚举属性 */

console.log(obj.propertyIsEnumerable('name')) // true

Object.defineProperty(obj, 'age', {
    
  value: '18',
})

Object.defineProperty(obj, 'like', {
    
  value: 'game',
  enumerable: true,
})

console.log(obj.age) // 18
console.log(obj.like) // game

/* 验证enumerable默认为false */
console.log(obj.propertyIsEnumerable('age')) // false
console.log(obj.propertyIsEnumerable('like')) // true

for (const key in obj) {
    
  console.log(key, obj[key])
}
/* name 测试可枚举属性 like game */
// 可以看到属性定义 enumerable: true 才会被 for...in遍历

4. 继承的可枚举属性

var obj = {
    
  name: '测试是否会遍历原型上的属性',
}

var triangle = {
     a: 1, b: 2, c: 3 }

function Person() {
    
  this.color = 'red'
}

Person.prototype = triangle

var obj = new Person()

for (var key in obj) {
    
  console.log(key, obj[key])
}
/* color red a 1 b 2 c 3 */

/* 正是因为 for...in 会遍历对象原型链上可枚举的属性,所以一般使用for...in的时候会结合hasOwnProperty方法,确保读取到的属性是当前对象上的 */
for (var key in obj) {
    
  if (obj.hasOwnProperty(key)) {
    
    console.log(key, obj[key])
  }
}
/* color red */

// ps 原型链上的可枚举属性都会被遍历

总结
写了几个 for…in 的验证案例,对 for…in 有一个初步的了解。

  1. 建议应用场景:
  • 需要遍历对象上的属性的时候;
  • ps 不太建议遍历数组
  1. 其次需要注意的点:
  • 迭代是任意顺序的
  • 属性需要可枚举
  • 注意 Symbol
  • 注意原型链上的可枚举属性
  1. 相关的方法
  • Object.defineProperty()

  • enumerable

  • Object.prototype.propertyIsEnumerable()

原网站

版权声明
本文为[lazytomato]所创,转载请带上原文链接,感谢
https://blog.csdn.net/wswq2505655377/article/details/126253983