踩坑经验:JavaScript 中的 for...of 和 for...in 循环

news2024/12/23 8:31:26

在 JavaScript 编程中,for...offor...in 是常用的循环语法,但它们在使用时可能会引发一些意想不到的问题。本文将分享我在使用这两种循环时所遇到的坑和经验。

两者的区别:

  1. 适用对象类型
    • for…of:主要用于遍历可迭代对象(例如数组、字符串、Set、Map等),可以获取到迭代对象的值。
    • for…in:主要用于遍历对象的属性(包括原型链上的属性),可以获取到属性名(键)。
  1. 遍历顺序
    • for…of:按照对象的顺序迭代,一般用于遍历有序集合。
    • for…in:无法保证属性的遍历顺序,可能会导致属性的无序输出。
  1. 迭代内容
    • for…of:迭代的是对象的值本身,例如数组中的元素、字符串中的字符等。
    • for…in:迭代的是对象的属性名,需要通过属性名访问属性值。
  1. 支持情况
    • for…of:在 ES6 中引入,适用于可迭代对象,如数组、字符串等。
    • for…in:在早期版本的 JavaScript 中就存在,用于遍历对象的属性。但是不适用于数组等可迭代对象,因为它会遍历出额外的属性。
  1. 性能
    • for…of:通常性能比 for…in 更好,因为它不需要遍历原型链上的属性。

示例代码演示两者的不同用法:

// for...of 遍历数组
const arr = [1, 2, 3, 4];
for (const element of arr) {
    console.log(element); // 输出数组的每个元素
}

// for...in 遍历对象的属性
const obj = { a: 1, b: 2, c: 3 };
for (const key in obj) {
    console.log(key);      // 输出属性名 a, b, c
    console.log(obj[key]); // 输出属性值 1, 2, 3
}
  // for...of 遍历数组
const arr = [1, 2, 3, 4];
for (const element of arr) {
    console.log(element); // 输出数组的每个元素
}

// for...in 遍历对象的属性
const obj = { a: 1, b: 2, c: 3 };
for (const key in obj) {
    console.log(key);      // 输出属性名 a, b, c
    console.log(obj[key]); // 输出属性值 1, 2, 3
}

总之,如果你想遍历数组或其他可迭代对象的值,使用 for…of;如果你想遍历对象的属性,使用 for…in

for…of 遍历数组的陷阱:

当使用 for...of 循环来遍历数组时,我们通常是为了遍历数组的元素,而不是索引。然而,在使用 for...of 循环时,有一些常见陷阱需要避免,特别是关于循环索引和遍历顺序的问题。下面是如何正确使用 for...of 循环来遍历数组,以及如何避免这些陷阱的解释:

1. 遍历元素而非索引: 使用 for...of 循环时,我们直接遍历数组的元素,而不需要关心索引的细节。这样可以使代码更加简洁易读。例如:


const array = [1, 2, 3, 4, 5];
for (const element of array) {
    console.log(element); // 输出数组的每个元素
}

2. 避免使用索引: 避免在 for...of 循环中使用额外的索引变量,因为 for...of 循环本身已经直接提供了数组的每个元素。这有助于减少代码复杂性和错误的机会。不推荐的写法:


const array = [1, 2, 3, 4, 5];
for (let i = 0; i < array.length; i++) {
    console.log(array[i]); // 避免这种额外使用索引的方式
}

3. 保持遍历顺序: for...of 循环保证按照数组中的顺序进行遍历,因此它适用于需要按顺序处理元素的场景。这确保了元素的处理顺序与它们在数组中的位置一致。

4. 不会遍历稀疏元素: for...of 循环不会遍历数组中的稀疏元素(未赋值的元素),只会遍历有实际值的元素。这有助于避免不必要的处理。

5. 适用于可迭代对象: 除了数组,for...of 循环还适用于其他可迭代对象,如字符串、Set、Map 等。这使得代码具有更广泛的适用性。

综上所述,使用 for...of 循环来遍历数组是一种更直观、简洁的方式,可以避免许多在传统 for 循环中容易犯的错误。通过专注于元素而非索引,保持遍历顺序,并充分利用循环的简洁性,我们可以提高代码的可读性和可维护性,减少错误的风险。

for…in 遍历对象的不可靠性:

在使用 for...in 循环时,可能会遇到一些问题,其中包括遍历顺序的不确定性和遍历到原型属性的风险。下面是对这些问题的探讨:

1. 遍历顺序的不确定性: for...in 循环无法保证遍历对象属性的顺序。这是因为对象属性在 ECMAScript 规范中被定义为无序的。因此,使用 for...in 循环来依赖属性遍历的特定顺序是不可靠的。

2. 遍历到原型属性的风险: for...in 循环会遍历对象自身属性以及继承自原型链的属性。这可能会导致意外的属性遍历,尤其是当我们只想遍历对象自身的属性时。

3. 原型属性被遍历:


function Person() {
    this.name = 'Alice';
}

Person.prototype.age = 30;

const person = new Person();

for (const prop in person) {
    console.log(prop); // 输出 'name' 和 'age'
}

/**
 * @param {Function} fn
 * @return {Array}
 */
array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
fn = function (n) {
    return String(n > 5);
}

Array.prototype.groupBy = function (fn) {
    const myMap = new Map();
    const keys = Object.keys(this);
    console.log(keys);
    for (const key in keys) {
      
        if (myMap.has(fn(this[key]))
        ) {
            myMap.set(fn(this[key]), myMap.get(fn(this[key])).concat([this[key]]));

        } else {
            myMap.set(fn(this[key]), [this[key]]);
        }

    }
    const myObj = {};
    for (const [key, value] of myMap) {
        myObj[key] = value;
    }

    return myObj;
};

array.groupBy(fn);
/**
 * [1,2,3].groupBy(String) // {"1":[1],"2":[2],"3":[3]}
 */

image.png

image.png
4. 使用 hasOwnProperty 过滤原型属性:


for (const prop in person) {
    if (person.hasOwnProperty(prop)) {
        console.log(prop); // 仅输出 'name'
    }
}

5. 遍历可枚举属性:


Object.defineProperty(person, 'country', {
    value: 'USA',
    enumerable: true
});

for (const prop in person) {
    console.log(prop); // 输出 'name'、'age' 和 'country'
}

6. 遍历不可枚举属性:


Object.defineProperty(person, 'address', {
    value: '123 Main St',
    enumerable: false
});

for (const prop in person) {
    console.log(prop); // 仅输出 'name' 和 'age'
}

7. 遍历顺序问题:


const obj = { a: 1, b: 2, c: 3 };

for (const prop in obj) {
    console.log(prop); // 输出 'a'、'b' 和 'c',但顺序不确定
}

8. 遍历字符串属性:


const str = 'Hello';

for (const char in str) {
    console.log(char); // 输出 '0'、'1'、'2'、'3' 和 '4'
}

综上所述,尽管 for...in 循环在某些情况下可以派上用场,但要特别小心遍历顺序的不确定性和遍历到原型属性的风险。在需要遍历对象属性时,推荐使用 Object.keysObject.valuesObject.entries 等方法,以获得更可靠的遍历结果。或者,考虑使用 for...of 循环来遍历数组和可迭代对象,以避免这些问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/891698.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

微信开发之一键删除好友的技术实现

简要描述&#xff1a; 删除联系人 请求URL&#xff1a; http://域名地址/delContact 请求方式&#xff1a; POST 请求头Headers&#xff1a; Content-Type&#xff1a;application/jsonAuthorization&#xff1a;login接口返回 参数&#xff1a; 参数名必选类型说明wI…

小红书运营 新号快速涨粉方法

大家好&#xff0c;我是网媒智星&#xff0c;今天跟大家分享一下小红书新号快速涨粉的方法。 新手博主在刚开始使用小红书时往往会陷入一个误区&#xff0c;他们热衷于发布自己认可的笔记&#xff0c;然后迫不及待地去查看数据&#xff0c;却发现没有获得赞赏和关注。 然而&…

微信小程序登录及登录态管理

一&#xff0c;小程序登录 小程序登录 | 微信开放文档 接口应在服务器端调用&#xff0c;详细说明参见服务端API。 接口说明 接口英文名 code2Session 功能描述 登录凭证校验。通过 wx.login 接口获得临时登录凭证 code 后传到开发者服务器调用此接口完成登录流程。更多使…

Android Framework 全局替换系统字体

基于Android 11 Android Framework 全局替换系统字体 第一种通过替换系统默认字体 将需要替换的字体资源放置frameworks/base/data/fonts/目录下。 将系统默认的Roboto字体替换为HarmonyOs字体。 frameworks/base/data/fonts/fonts.xml frameworks/base/data/fonts/Android.…

Docker容器与虚拟化技术:Docker镜像创建、Dockerfile实例

目录 一、理论 1.Docker镜像的创建方法 2.Docker镜像结构的分层 3.Dockerfile 案例 4.构建Systemctl镜像&#xff08;基于SSH镜像&#xff09; 5.构建Tomcat 镜像 6.构建Mysql镜像 二、实验 1.Docker镜像的创建 2. Dockerfile 案例 3.构建Systemctl镜像&#xff08;…

AI抢饭碗!新闻集团将使用生成式AI,每周自动写3000篇新闻丨IDCF

作者&#xff1a;AIGC开放社区 8月1日&#xff0c;英国卫报消息&#xff0c;全球最大新闻媒体公司之一的新闻集团&#xff0c;将使用生成式AI每周自动创建3000篇澳大利亚本地新闻。 据悉&#xff0c;新闻集团在内部成立了一个名为“Data Local”的部门只有4名员工&#xff0c;…

爱校对:塑造无瑕公文的强大工具

在公文处理的世界中&#xff0c;每个字、每个标点都需要细心打磨&#xff0c;确保无一瑕疵。如何能达到这种精确无误的程度呢&#xff1f;让我们一起来看看强大的爱校对软件如何帮助我们塑造无瑕的公文。 首先&#xff0c;爱校对软件采用先进的自然语言处理和深度学习技术&…

IDA远程调试真机app

IDA远程调试真机app 第一步&#xff1a;启动 android_server&#xff0c;并修改端口 # 启动android_server ./android_server -p31928第二步&#xff1a;端口转发、挂起程序 # 端口转发adb forward tcp:31928 tcp:31928# 挂起程序 adb shell am start -D -n com.qianyu.antid…

shell和Python 两种方法分别画 iostat的监控图

在服务器存储的测试中,经常需要看performance的性能曲线&#xff0c;这样最能直接观察HDD或者SSD的性能曲线。 如下这是一个针对HDD跑Fio读写的iostat监控log,下面介绍一下分别用shell 和Python3 写画iostat图的方法 1 shell脚本 环境:linux OS gnuplot工具 第一步 :解析iosta…

Mysql分表后同结构不同名称表之间复制数据以及Update语句只更新日期加减不更改时间

场景 SpringBootMybatis定时任务实现大数据量数据分表记录和查询&#xff1a; SpringBootMybatis定时任务实现大数据量数据分表记录和查询_mybatis 定时任务创建日表_霸道流氓气质的博客-CSDN博客 通过以上分表实现的同结构不同表名之间的表&#xff0c;如何将一个表中的数据…

Flink学习笔记(一)

流处理 批处理应用于有界数据流的处理&#xff0c;流处理则应用于无界数据流的处理。 有界数据流&#xff1a;输入数据有明确的开始和结束。 无界数据流&#xff1a;输入数据没有明确的开始和结束&#xff0c;或者说数据是无限的&#xff0c;数据通常会随着时间变化而更新。 在…

python模块中的_all__属性的作用

文章目录 前言 一、python模块中的_all__属性的作用 总结 前言 python模块中的特殊变量_all__的用法总结。 一、python模块中的_all__属性的作用 顾名思义&#xff1a;我们如果导一个包里面的函数或者变量&#xff0c;会把暴露在外部的变量和函数导出。那么有些变量或者函…

如何做好小程序的运营,有哪些运营策略?

小程序用完即走的特性&#xff0c;使得小程序留存用户比较困难。任何一个产品的出现&#xff0c;绕不过推广运营这个话题&#xff0c;小程序也是一样。抓住用户&#xff0c;培养用户的忠诚度是所有产品的根本&#xff0c;我们该怎样从零开始运营好小程序&#xff1f; 一、人群…

免费批量ppt转pdf?一个方法教你完美转换

随着科技的不断发展&#xff0c;电子文档的使用越来越普遍。在商业、教育和个人领域&#xff0c;我们经常需要将PPT文件转换为PDF格式&#xff0c;以便更方便地共享和存档。幸运的是&#xff0c;现在有许多在线工具和软件可以帮助我们轻松地完成免费批量ppt转pdf。下面将介绍一…

LabVIEW开发设计热稳定器

LabVIEW开发设计热稳定器 使用与PC控制单元接口的电子设备进行数据采集和控制已广泛用于不同的工业应用。精确的温度控制是一个巨大的挑战&#xff0c;这就是为什么一些工业应用需要使用适当的材料和设备比更好的温度精度。 ​ 为了追踪[-50至250C]之间的温度变化&#xff0c…

【LeetCode】205. 同构字符串

205. 同构字符串&#xff08;简单&#xff09; 方法&#xff1a;哈希映射 思路 判断两个字符串是不是同构字符串&#xff0c;只需要判断对应的字符是不是存在映射关系&#xff0c;我们可以使用 map 来保存字符间的映射关系。由于 “不同字符不能映射到同一个字符上&#xff0…

babylonjs基于自定义网格生成围栏动画

效果&#xff1a; import { Vector3, Mesh, MeshBuilder, StandardMaterial, Texture, Animation, Color3 } from "babylonjs/core"; import imgUrl from "./image/headerwangge2.png" // 创建模型护栏特效 export default class CreateRail {constructor…

Flutter实战·第二版-第三章 基础组件笔记

第三章&#xff1a;基础组件 3.1文本及样式 3.1.1 Text Text("Hello world",textAlign: TextAlign.left, );Text("Hello world! Im Jack. "*4,maxLines: 1,overflow: TextOverflow.ellipsis, );Text("Hello world",textScaleFactor: 1.5, );3.1…

重塑DTC规则:元气森林的全渠道转型

元气森林作为迄今为止用5-6年时间最快达到70亿年销售额的饮料品牌&#xff08;统一、可口可乐、东鹏特饮都花了15年左右&#xff0c;康师傅花了10年&#xff09;。元气森林于2016年在北京创立&#xff0c;凭借健康产品理念和新潮营销方式&#xff0c;一款主打“0糖0卡0脂”概念…

javaScript:模板字符串让你忘记字符串拼接

目录 一.前言 二.模板字符串的使用 1.介绍 2.模板字符串 支持换行 模板字符串更适合元素写入 innerHTML模板字符串写法 3.模板字符串中&#xff0c;可以运行表达式 4.模板字符串中可以运行函数 三.总结 语法&#xff1a; 多行字符串&#xff1a; 变量插值&#xff1a; …