语法
for ([initialization]; [condition]; [final-expression]) { statement }
initialization
一个表达式 (包含赋值语句) 或者变量声明。典型地被用于初始化一个计数器。该表达式可以使用var或let关键字声明新的变量,使用var声明的变量不是该循环的局部变量,而是与for循环处在同样的作用域中。用let声明的变量是语句的局部变量。该表达式的结果无意义。注意此处的let 和 var 声明表达式的不同点
condition
一个条件表达式被用于确定每一次循环是否能被执行。如果该表达式的结果为true, statement 将被执行。 这个表达式是可选的。如果被忽略,那么就被认为永远为真。如果计算结果为假,那么执行流程将被跳到for语句结构后面的第一条语句。
final-expression
每次循环的最后都要执行的表达式。执行时机是在下一次condition的计算之前。通常被用于更新或者递增计数器变量。
statement
只要condition的结果为true就会被执行的语句。 要在循环体内执行多条语句,使用一个块语句({ ... })来包含要执行的语句。没有任何语句要执行,使用一个空语句(;)。 可以使用break 主动跳出循环
初始化中使用var声明的变量不是该循环的局部变量,而是与for循环处在同样的作用域中,使用let声明的则在局部变量中
初始化块中的表达式都是可以省略的,如果省略则需要在语句块中设置跳出条件,避免进入死循环
在for循环内部使用异步函数、闭包等时的问题:
setTimeOut等异步函数时:
var arr = [1,3,5,7,9]; for (var i = 0; i < arr.length-1; i++) { setTimeout(function() { console.log("循环的值:"+i); console.log("数组对应的值:"+arr[i]); }, 1000); }
存在闭包时:
function box() { var arr = []; for (var i = 0; i < 5; i++) { arr[i] = function () { return i; //由于这个闭包的关系,他是循环完毕之后才返回,最终结果是4++是5 } //这个匿名函数里面根本没有i这个变量,所以匿名函数会从父级函数中去找i, } //当找到这个i的时候,for循环已经循环完毕了,所以最终会返回5 return arr; } let boxArr = box(); console.log(boxArr[0]())
这时,会产生与我们预期所想得到的效果不同的结果,导致出现这种情况的原因主要是 for语句表达式中初始化中的变量不是该循环的局部变量(子作用域),而是与for循环处在同样的作用域中(父作用域)。
因此,解决方案比较流行的有两种:
第一种:使用let 替代 var 声明for循环的表达式(推荐)
function box() { var arr = []; for (let i = 0; i < 5; i++) { arr[i] = function () { return i; } } return arr; } let boxArr = box(); console.log(boxArr[0]())
var arr = [1,3,5,7,9]; for (let i = 0; i < arr.length-1; i++) { setTimeout(function() { console.log("循环的值:"+i); console.log("数组对应的值:"+arr[i]); }, 1000); }
第二种:使用自执行函数利用闭包特性来达到效果:
var arr = [1, 3, 5, 7, 9]; for (var i = 0; i < arr.length ; i++) { (j=>{ setTimeout(() =>{ console.log("循环的值:" + j); console.log("数组对应的值:" + arr[j]); }, 1000); })(i) }
function box() { var arr = []; for (var i = 0; i < 5; i++) { ((j)=>{ arr[j] = ()=> j; })(i); } return arr; } let boxArr = box(); console.log(boxArr[0]()) console.log(boxArr[1]())
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/104108.html
摘要:如图遍历数组遍历数组元素并以某种方式处理每个元素是一个常见的操作。如图不过,里的功能比较强大,可以遍历而且返回值是的则被省略掉总结遍历对象,遍历出来的是键名,而不是键值,参数必须是对象。 可能是由于职业的关系,下班之后完全不想Open PC,但很多知识点有必要自己做个小小总结。本人之前对原生Array和Object完全没概念。 遍历对象的方法: Object.keys(Object)...
摘要:异步那些事一基础知识异步那些事二分布式事件异步那些事三异步那些事四异步那些事五异步脚本加载事件概念异步回调首先了讲讲中两个方法和定义和用法方法用于在指定的毫秒数后调用函数或计算表达式。功能在事件循环的下一次循环中调用回调函数。 JS异步那些事 一 (基础知识)JS异步那些事 二 (分布式事件)JS异步那些事 三 (Promise)JS异步那些事 四(HTML 5 Web Workers...
摘要:一个对象如果要有可被循环调用的接口,就必须在的属性上部署遍历器生成方法原型链上的对象具有该方法也可。阮大神案例上面代码是一个类部署接口的写法。属性对应一个函数,执行后返回当前对象的遍历器对象。 最近看阮一峰阮大神的ES6,刚刚看到Iterator和for...of循环这一章,小作笔记跟大家略微分享一下,不足之处还望大家多多指正 Iterator(遍历器)就是一种机制;任何数据结构只要是...
摘要:委托上面的代码结合了构造函数和原型两种方式去创建对象,首先聊聊构造函数构造函数构造函数本质上还是函数,只不过为了区分将其首字母大写了而已。注意注释掉的代码是自动执行的,但这并不是构造函数独有的,每个函数在声明时都会自动生成。 首先看看下面两个1+1=2的问题: 问题一:为什么改变length的值,数组的内容会变化? var arr = [1]; arr.length = 3; aler...
摘要:概述本篇主要介绍的运行机制单线程事件循环结论先在中利用运行至完成和非阻塞完成单线程下异步任务的处理就是先处理主模块主线程上的同步任务再处理异步任务异步任务使用事件循环机制完成调度涉及的内容有单线程事件循环同步执行异步执行定时器的事件循环开始 1.概述 本篇主要介绍JavaScript的运行机制:单线程事件循环(Event Loop). 结论先: 在JavaScript中, 利用运行至...
阅读 1345·2021-09-24 10:26
阅读 1674·2019-08-30 14:14
阅读 2050·2019-08-29 16:54
阅读 342·2019-08-29 14:09
阅读 1451·2019-08-29 12:55
阅读 906·2019-08-28 18:13
阅读 1542·2019-08-26 13:39
阅读 2531·2019-08-26 11:43