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


    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 进行排序,自然数是按照大小升序进行排序,其他两种都是按照插入的时间顺序进行排序。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    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
    */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    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遍历
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    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 原型链上的可枚举属性都会被遍历
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

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

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

    • enumerable

    • Object.prototype.propertyIsEnumerable()

  • 相关阅读:
    带讲解的自行车租赁系统,可做毕设/课设
    BTree vs B+Tree 节点操作流程图解
    JS服务端技术—Node.js知识点锦集
    如何确保亚马逊、速卖通等平台测评补单的环境稳定性和安全性?
    阿里云国际站:技术再升级,阿里云支持金融机构打造互动体验型超级移动端
    大学生个人网页设计 HTML个人网页制作 web个人网站模板 简单静态HTML个人网页作品
    torch实现Gated PixelCNN
    【Vue 开发实战】基础篇 # 12:常用高级特性provide/inject
    【产品经理修炼之道】- 需求挖掘之员工计件
    [附源码]计算机毕业设计JAVA医疗预约系统
  • 原文地址:https://blog.csdn.net/wswq2505655377/article/details/126253983