JavaScript中for...of和for...in的区别详解

作者:代码拾荒时间:2026-10-30 20:57:32浏览:239

本文详细解析JavaScript中for...of与for...in遍历语句的核心区别。for...of基于ES6迭代器协议,适用于数组、字符串等可迭代对象,直接获取值;而for...in用于遍历对象键名。文章深入讲解Symbol.iterator接口与next方法机制,并提供处理普通对象遍历的多种方案。

首先介绍for...of循环。

for...of是ES6引入的新特性。其最直观的表现是:使用for...of遍历数组时,直接输出的是元素的值(value),这与for...in输出索引值(index)形成鲜明对比,这也是初学者最容易感知的差异。

其次,for of无法直接用于遍历普通的对象,它仅能遍历那些部署了iterator(迭代器)接口的类数组对象。

那么,究竟什么是iterator呢?

迭代器(Iterator)是一种提供统一访问机制的接口。任何数据结构只要部署了Iterator接口,即可通过遍历操作依次处理其所有成员。

以下示例展示了for...of无法直接遍历普通对象的情况:

let obj2 = { x: 1,y: 2, z: 3,};
for (const value of obj2) {
  console.log(value);
}
//遍历时出错
//Uncaught TypeError: obj2 is not iterable

原因在于普通对象并非可迭代对象。可迭代对象是指实现了迭代器协议的对象,该协议要求对象必须部署iterator方法,即挂载在原型上的Symbol(Symbol.iterator)方法。因此,使用for...of处理数组时,实际是调用了数组原型下的该方法。每次调用后,方法内部返回next方法,这相当于一个“指针”,下次调用时该“指针”向后移动。

对此,部分同学可能仍感到困惑,此处通过一个示例进行说明:

let obj = {
  data: [1, 2, 3],
  // 这里给对象实现了一个迭代器方法
  [Symbol.iterator]() {
    let index = 0;
    const data = this.data;
    return {
      next() {
        if (index < data.length) {
          return {  value: data[index++], done: false, };
        } else {
          return { done: true };
        }
      },
    };
  },
};
for (const value of obj) {
  console.log(value);
}//1 2 3

经过上述处理,我们便为对象实现了迭代器方法,从而可以使用for...of遍历该obj对象。这段代码可能令人费解,主要源于对Symbol.iterator和next方法的不熟悉,下面简要介绍这两个概念。

  • Symbol.iterator是一个函数属性,其返回值是一个迭代器对象。在对象中定义该属性后,当使用for of时,语言机制会寻找该方法,即next方法。在对象中使用此属性即覆盖了默认迭代器,从而实现自定义逻辑。
  • 其次我们要注意返回的迭代器对象:我们要知道,迭代器对象是要带有next方法的对象,而且这个next方法的返回值还必须是一个包含value和done的对象。其中value是当前值,而done表示是否全部遍历完成.
  • 迭代器通常如何工作?无论是数组、对象、集合还是其他数据结构,迭代器中均提供了next方法。每次调用next方法都会返回这个数据集合的下一个值。联想到C语言中“指针”的移动,这也就解释了为何需要next方法。
  • 因此,这部分代码变得易于理解:我们实现了Symbol.iterator方法,在内部定义索引index并获取data数组,随后return一个包含next方法的迭代器对象。若当前索引小于数组长度,则返回包含当前value值和done(false,表示迭代未完成)的对象;否则返回done为true的对象,表明迭代事件已完成。

经过上述处理,大家可以看到这种方式较为繁琐。若不想通过此方式获取每个值,只能采用其他巧妙手段:避免直接遍历对象,而是通过某种方法进行过渡处理。

因此,若使用for...of迭代对象,必须通过特定手段进行加工处理。

let sum = 0;
let obj3 = {x: 1,y: 2, z: 3,};
for (const value of Object.values(obj3)) {
  sum += value;
}
console.log(Object.values(obj3));//[1,2,3]
console.log(sum);//6

此处使用了Object.values方法获取对象中的值,处理后返回一个包含对象值的数组。像数组、Map、Set、字符串等内置迭代器的类型,均可使用for...of进行迭代处理。此外,还可使用Object.entries()和Object.keys()等方法处理,此处不再展开。

接下来介绍for...in循环。

在介绍完for...of后,紧接着说明for in。for in最直接的体现是它能直接遍历处理对象类型数据,无需像for...of那样增加迭代器属性。具体介绍如下:

let obj4 = {
  hobby: "唱,跳,rap",
  name: "kun",
  sex: "男",
};
for (const key in obj4) {
  console.log("属性名" + key, "属性值" + obj4[key]);
}

采用这种方式不会报错,可正常打印输出值。因此,在实际场景中处理对象时通常使用for...in;而遇到字符串、Map等自带迭代器的类型,则交给for...of处理,具体场景具体分析。

这也印证了前文所述:使用for...in时打印的是key值,因此要获取属性值需通过obj4[key]。

同样,使用for...in也可处理Map、Set、String等类型数据。但与for...of最显著的区别在于,我们可以直接处理普通对象。

总结

本文解释了for...of为何不能处理普通对象及其处理方法,并介绍了每种方法适用的问题场景。因此,使用时需根据具体场景进行分析处理。

到此结束关于JavaScript中for...of和for...in区别详解的介绍。更多相关内容请搜索本站以往文章或继续浏览下方相关文章,希望大家以后多多支持本站!

作者最新文章