for ([initialization]; [condition]; [final-expression]) { statement }
initialization
一个表达式 (包含赋值语句) 或者变量声明。典型地被用于初始化一个计数器。该表达式可使用var或let关键字声明新的变量,使用var声明的变量不是该循环的局部变量,而是与for循环处在一样的做用域中。用let声明的变量是语句的局部变量。该表达式的结果无心义。注意此处的let 和 var 声明表达式的不一样点express
condition
一个条件表达式被用于肯定每一次循环是否能被执行。若是该表达式的结果为true, statement 将被执行。 这个表达式是可选的。若是被忽略,那么就被认为永远为真。若是计算结果为假,那么执行流程将被跳到for语句结构后面的第一条语句。
final-expression
每次循环的最后都要执行的表达式。执行时机是在下一次condition的计算以前。一般被用于更新或者递增计数器变量。
statement
只要condition的结果为true就会被执行的语句。 要在循环体内执行多条语句,使用一个块语句({ ... })来包含要执行的语句。没有任何语句要执行,使用一个空语句(;)。 可使用break 主动跳出循环数组
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); }
第二种:使用自执行函数利用闭包特性来达到效果:spa
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]())