对话梳理关于for...in和for...of的相关问题

113 阅读4分钟

🚦 写在前面

过年那会读大一计算机专业的表妹问到我

for循环中 inof 有什么办法可以一下子就记住它们的区别

以前上学时记忆当中就是 for key infor value of, 根据介词一个是in一个是of

现在上班后既然有空余时间(而且有个掘金.日新计划),斗胆把这个老生常谈的课题再拿出来探究探究记录记录

🧘 有兴趣的同学跟着我的文字继续看下去吧!

🚦 问答环节

1、遍历什么

  • for...in
    • 遍历->
      • 除了Symbol以外的可枚举属性的对象
    • [语法]: for (变量 in object) { ... }
    • 变量: 在每次迭代中,这个变量会被赋值为不同的属性名
  • for...of
    • 遍历->
      • Array(数组)、
      • Map(映射)、
      • Set(集合)、
      • String(字符串)、
      • TypedArray(类数组)、
      • Arguments对象
    • [语法]: for (变量 of iterable) { ... }
    • 变量: 在每次迭代中,这个变量会被赋值为不同的属性的值

2、for...in为什么一般用来遍历对象 不建议用来遍历数组

表妹来了一句:我看你这里for...in只写了遍历对象,为什么很多同学用for...in遍历数组\字符串同样没问题,我试过确实是没问题的。

答: for...in是为了遍历对象属性而构建的,不建议用来遍历数组。

注意: for...in遍历,会有以下问题需要关注。

  • 第一:遍历顺序有可能不是按照实际内部顺序来输出的,举个例子:
const obj = {
    1: 'a',
    3: 'b',
    2: 'c'
}

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

// 输出来的是
// 1 a
// 2 c
// 3 b
  • 第二:遍历出来的属性名key是字符串,而不是数字。
const arr = []
arr[2] = 'c'
arr[1] = 'b'
arr[0] = 'a'

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

// 输出来的是
// 0 a string
// 1 b string
// 2 c string
  • 第三:所有可枚举的属性都会被遍历出来,包括原型链上的属性,举个例子:
Array.prototype.foo = 1

const arr = [1, 2, 3]

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

// 输出来的是
// 0 1
// 1 2
// 2 3
// foo 1
Array.prototype.last = function () {
    return this[this.length - 1]
}

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

// 输出来的是
// last

题外话:解决第三点所有枚举属性都会输出的办法,用hasOwnProperty来确定某属性是不是它本身属性先。即使解决了这一点,它的速度是慢的,因为需要遍历数组所有属性包括原型链上的属性。

所以文档中说到for...in是为了遍历对象属性而构建的,不建议用来遍历数组。 javascript的数组也继承自Object,所以也能够用for...in遍历,但是以上几点都是要考虑的,三个字:不建议。

对于数组,还是用for、for...of、forEach等等其他的遍历比较好。(for...of遍历的只是其中的元素,不包括原型属性和索引这些。)

3、for...in for...of这两种如何终止循环

for...in 和 for...of 都能用break来终止循环 都能用continue来跳出本次循环

4、除了for...in用来循环对象,还有什么办法可以循环对象

循环对象,除了for...in

  • 还有
    • Object.keys 返回一个由属性组成的数组
       const obj = {
           a: 1,
           b: 2,
           c: 3
       }
       console.log(Object.keys(obj)) // ['a', 'b', 'c']
    
    • Object.values 返回一个由属性值组成的数组
       const obj = {
           a: 1,
           b: 2,
           c: 3
       }
       console.log(Object.keys(obj)) // [1, 2, 3]
    
    • Object.entries 返回一个键值对数组
       const obj = {
           a: 1,
           b: 2,
           c: 3
       }
       console.log(Object.entries(obj))
       
       [       ['a', 1],
           ['b', 2],
           ['c', 3],
       ]
    
    • Reflect.ownKeys 跟Object.keys类似
    • Object.getOwnPropertyNames
       const obj = {
           a: 1,
           b: 2,
           c: 3
       }
       console.log(Object.getOwnPropertyNames(obj)) // ['a', 'b', 'c']
    

🚦 总结

  • for...in 遍历的变量是索引(即属性)、而 for...of 是 元素值(即属性的值)
  • for...in 和 for...of 都能用break来终止循环 都能用continue来跳出本次循环
  • for...in是为了遍历对象属性而构建的,不建议用来遍历数组

当你成功的时候,你说的所有话都是真理。 ——阿里巴巴集团创始人马云

Whatever you say is taken for a truth while you are in success.

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 1 天 点击查看活动详情