在JavaScript中,我们经常需要去循环迭代方法操作数组对象等,常见等循环方法有 forfor infor offorEach等。

1.for循环

for循环是最基础常见的一种循环,圆括号中需要三个表达式,由分号分隔,最后面是一个花括号的块语句。

for (var i = 0; i <10; i++){if (i === 5) {continue; //跳出当前循环} else if (i === 8) {break;    //结束循环}console.log(i);
}

for循环中的语句

continue 语句用来跳出本次循环,但会继续执行后面的循环。
break 语句用来结束循环,后面的循环不会再执行。
⚠️return 并不能用来跳出for循环,return语句只能出现在函数体内,它会终止函数的执行,并返回一个指定的值。

使用for循环中遇到的问题

你可能会遇到在for循环使用一个异步操作,这也是一个很常见的面试题。在如下场景,你需要将一批id从0到9的用户名数据请求回来,并将id做为key,name为value塞到一个对象里,代码可能会是这样的

var users = {};
for (var i = 0; i < 10; i++) {ajax.get(`/api/userName/${i}`).then(res => {users[i] = res.name;});
}

最后users对象的数据结果并非我们所想的那样,而是{10: '最后一个请求回来的用户名'}。这是因为异步请求的原因,由于事件队列机制,for循环会先全部执行完成,而异步请求会在后面的不定时间内完成,并且调用then方法被事件队列排在了后面,而此时在任意一个then方法内i变量已经在最后一次循环中被递增到等于10,在不停的调用then方法时,users对象key为10的value会被一直改写直到最后一个请求结束。

使用 let 块级作用域解决

var users = {};
for (let i = 0; i < 10; i++) {ajax.get(`/api/userName/${i}`).then(res => {users[i] = res.name;});
}

将递增变量i使用let声明即可解决,let 语句声明一个块级作用域的本地变量,花括号里是一个块,每次循环都使用该块级作用域中的变量,可以看作每次循环的块都是相互隔离的,变量只会在该作用域内生效。

使用函数闭包作用域解决

var users = {};
for (var i = 0; i < 10; i++) {(function () {var j = i;ajax.get(`/api/user/${j}`).then(res => {users[j] = res.name;});}());
}

我们将异步方法包在一个立即执行函数里面,通过var j声明的变量去承接在该函数内i变量的值,由于立即执行函数形成了一个闭包作用域,变量j在每一个作用域内都是单独存在的。

使用函数参数作用域解决

var users = {};
for (var i = 0; i < 10; i++) {(function (value) {ajax.get(`/api/user/${value}`).then(res => {users[value] = res.name;});}(i));
}

将变量i作为立即执行函数的参数传递进来,参数也具有各自的作用域,函数参数只在函数内起作用,是局部变量。

2.for in循环(es5)

for...in语句以任意顺序遍历一个对象的可枚举属性,遍历的顺序可能因浏览器实现方式有所不同。所遍历的内容可以是一个对象、数组、字符串、arguments等。使用Object.defineProperty方法可以为对象属性定义是否可以枚举。

枚举

在JavaScript中,对象的属性分为可枚举和不可枚举之分,它们是由属性的enumerable值决定的。可枚举性决定了这个属性能否被for…in查找遍历到。对象的propertyIsEnumerable方法可以判断此对象是否包含某个属性,并且返回这个属性是否可枚举。
Object, Array, Number等内置的方法和属性都是不可枚举的

const obj = {};
Object.defineProperty(obj, 'city', {value: '北京', enumerable: false});
const isEnumerable = obj.propertyIsEnumerable('city');
console.log(obj);           // {city: "北京"}
console.log(isEnumerable);  //false

for...in可以遍历可枚举但对象,包括不是它本身但存在于原型链上的属性。

const obj = {a:1, b:2, c:3};
Object.defineProperty(obj, 'd', {value: 4, enumerable: false})
obj.__proto__ = {name: 'ricky', age: '25'}console.log(obj)console.log('=====for in=======')
for (var prop in obj) {console.log(prop, obj[prop]);
}
console.log('=====Object.keys=======')
console.log(Object.keys(obj))
console.log('=====Object.getOwnPropertyNames=======')
console.log(Object.getOwnPropertyNames(obj))
console.log('=====Object.values=======')
console.log(Object.values(obj))
console.log('=====Object.entries=======')
console.log(Object.entries(obj))

输出结果

我们先使用对象字面量的方式定义量一个obj,然后使用Object.defineProperty方法定义key为d的一个不可枚举属性,然后修改原型链__proto__,为其赋值了name, age两个属性。

  1. for in遍历出除属性名为d以外的所有可枚举属性,包括其原型链上的属性
  2. Object.keys方法会返回一个由对象的自身可枚举属性名(key)组成的数组,其原型链上的属性没有被包含
  3. Object.getOwnPropertyNames方法会返回一个由对象的自身所有属性名(key)组成的数组,包括可枚举和不可枚举的属性
  4. Object.values方法会返回一个由对象的自身可枚举属性的值(value)组成的数组
  5. Object.entries方法会返回一个由对象的自身可枚举属性的键值对(key和value)组成的数组

for in会循环所有可枚举的属性,包括对象原型链上的属性,循环会输出循环对象的key,如果循环的是一个数组则会输出下标索引(index)。

in 运算符

in 运算符测试一个对象其自身和原型链中是否存在该属性。

const obj = {name: 'ricky'};
Object.defineProperty(obj, 'city', {value: '北京', enumerable: false})
obj.__proto__ = {age: '25'}console.log('name' in obj);   // true
console.log('city' in obj);   // true
console.log('age' in obj);    // true
console.log('sex' in obj);    // false

for of(es6) 循环可迭代对象

for of循环可迭代对象(包括 Array,Map,Set,String,TypedArray,类数组的对象(比如arguments对象、DOM NodeList 对象)、以及Generator生成器对象等)。

const array = [{a: 1}, {b: 2}, {c: 3}];
array.name = 'ricky';console.log(array)
console.log('=====for of=======')
for (var prop of array) {console.log(prop);
}
console.log('=====for in=======')
for (var prop in array) {console.log(prop);
}

for of 与 for in 不同处

  1. 与for in不同的是,for of不能循环普通对象({key: value})
  2. for of不会将循环对象中自定义的属性内容循环出来
  3. for in 是遍历键名(key或index),而for of是遍历键值(value)。

forEach、map 循环

forEach() 方法对数组的每个元素执行一次提供的函数,其中函数有三个参数,依次为:当前循环项的内容、当前循环的索引、循环的数组。

const array = ['a', 'b', 'c'];
array.forEach(function(value, index, data) {console.log(value, index, data);
});
// 输出
// a  0  ["a", "b", "c"]
// b  1  ["a", "b", "c"]
// c  2  ["a", "b", "c"]

map() 方法会依次循环每一项,并且返回结果映射组成一个新的数组。

const array = [1, 2, 3];
const newArray = array.map(function(value, index, data) {return value * 2;
});
console.log(newArray);
//输出 [2, 4, 6]

使用forEach、map不能中断循环,方法会将每项内容都执行完成才会结束循环。

使用every或 some 提前结束循环

every循环当返回false时循环即会结束, some方法在循环返回true时结束循环,利用这个特性使用every和some方法都可以跳出循环。

const arr = [1, 2, 3, 4, 5];
arr.every(function(value){console.log(value);if(value === 3) {//every 循环当返回false时结束循环return false;}return true //every 循环需要返回true,没有返回值循环也会结束
});arr.some(function(value){console.log(value);if(value === 3) {//some 循环当返回true时结束循环return true;}
});

JavaScript中 for、for in、for of、forEach等使用总结相关推荐

  1. JavaScript中foreach()用法及使用的坑

    JavaScript中foreach()用法及使用的坑 JavaScript中foreach是用于遍历数组的方法,将遍历到的元素传递给回调函数,遍历的数组不能是空的要有值. foreach 语法: [ ...

  2. html5有foreach吗,JavaScript中的map()和forEach()有什么区别?

    来源:https://medium.com/better-programming,作者:Moon,翻译:公众号<前端全栈开发者> JavaScript中一些最受欢迎的功能可能是map和fo ...

  3. JavaScript中for、for...in、for...of、forEach的区别和用法

    JavaScript中for.for...in.for...of.forEach的区别和用法 for循环 forEach循环 for...in循环 for...of循环 总结 for循环 基本语法格式 ...

  4. JavaScript中遍历数组的for for-in和forEach三种方式

    JavaScript中遍历数组的for for-in和forEach三种方式 for循环 let arr = [1,2,3,4,5,6];for(let i = 0; i < arr.lengt ...

  5. JavaScript 中的forEach()方法

    JavaScript 中的forEach方法 一.forEach()的定义和用法? 1.第一个是数组的每一项值(必选) 2.第二个是数组下标(可选) 3.第三个是原数组(可选) 4.forEach() ...

  6. 必看干货:如何在 JavaScript 中实现 8 种基本图形算法

    在本文中,我将实现8 种图算法,探索 JavaScript 中图的搜索和组合问题(图遍历.最短路径和匹配). 这些问题是从<Java编程面试要素>一书中借来的.本书中的解决方案是用 Jav ...

  7. 详谈Javascript中的深拷贝和浅拷贝

    数据复制是我们编程中经常会使用到的技术,对于普通数值数据来说,复制很简单,但是对于复杂类型比如对象的复制,就会有很多需要考虑的东西,比如我们经常说到的深拷贝和浅拷贝. 浅拷贝 复制的对象和原始对象属性 ...

  8. django中的for循环_深入了解 JavaScript 中的 for 循环

    在ECMAScript5(简称 ES5)中,有三种 for 循环,分别是: 简单for循环 for-in forEach 在2015年6月份发布的ECMAScript6(简称 ES6)中,新增了一种循 ...

  9. JavaScript中的面向对象程序设计

    本文内容目录顺序: 1.Object概念讲述: 2.面向对象程序设计特点: 3.JavaScript中类和实例对象的创建: 4.原型概念: 5.原型API: 6.原型对象的具体使用:7.深入理解使用原 ...

最新文章

  1. asp.net 发送邮件代码
  2. 【译】 Diving Into The Ethereum VM Part 6 - How Solidity Events Are Implemented
  3. Linux系统下UDP发送和接收广播消息小样例
  4. 6.24AppCan移动开发者大会价值30万的展示机会归了谁?
  5. java中的动态代理----自己手动实现
  6. 未来客:人人都可以构建软件或系统
  7. 【无人机】无人机产业链全景图
  8. 东方韵味传统迎接新年|旭日东升的吉利日出好运插画素材模板
  9. Qualcomm 推出下一代物联网专用蜂窝技术芯片组!
  10. 返回值带头信息 php_php与Redis实现分布式锁
  11. Unix/Linux编程实践教程(1)---Unix系统编程概述
  12. HQChart使用教程78-分时图集合竞价
  13. 基于java+swing的物业收费管理系统(java+swing+Gui)
  14. RTKLIB源码调试.trace文件解析.stat文件解析
  15. inprivate浏览是什么意思_inprivate浏览是什么意思,怎样关闭inprivate浏览器
  16. 【Kay】MySQL必会常用函数
  17. 超出superView的subview响应方法
  18. 12个思维导图工具,像数据科学家一样结构化地思考
  19. 12.8 drf 村长项目
  20. maven怎么和ecli_傻瓜式教你安装maven以及Eclipse搭建maven环境

热门文章

  1. 长见识!居然还有程序员考公指南这种东西?
  2. 张一鸣批员工上班时聊游戏:老板好不好,看员工敢不敢怼他
  3. core data 学习笔记
  4. 【原创】分布式之缓存击穿 【原创】自己动手实现静态资源服务器 【原创】自己动手实现JDK动态代理...
  5. 腾讯、网易邮箱设置POP3客户端代理
  6. npoi上传xlsx文件,并读取数据
  7. Android Studio简单设置
  8. ASP.NET安全问题--ASP.NET中的授权问题(前篇)
  9. 写了一个将VxWorks的shell打印输出到指定内存中的接口,可广泛用于CLI下的调试函数显示以及故障自动捕获等功能,稍作修改可以适合其它嵌入式OS...
  10. 谈 JavaScript 浮点数计算精度问题(如0.1+0.2!==0.3)