摘要:闭包在循环中的应用延迟函数的回调会在循环结束时才执行事实上,当定时器运行时即使没给迭代中执行的是多有的回调函数依然是在循环结束后才会被执行,因此会每次输出一个出来。
闭包在循环中的应用
延迟函数的回调会在循环结束时才执行;
事实上,当定时器运行时即使没给迭代中执行的是 setTime(..., 0),多有的回调函数依然是在循环结束后才会被执行,因此会每次输出一个6出来。
for(var i=1; i<=5; i++){ setTimeout( function timer(){ let temp = new Date(); console.log(i + "----" + temp.toLocaleTimeString() + "." + temp.getMilliseconds()); }, i*1000); if(i == 5){ var now = new Date(); console.log("for循环结束----"+now.toLocaleTimeString() + "." + now.getMilliseconds()); } } // for循环结束----下午7:51:29.885 // 6----下午7:51:30.885 // 6----下午7:51:31.885 // 6----下午7:51:32.885 // 6----下午7:51:33.885 // 6----下午7:51:34.885利用立即执行函数创建作用域,但作用域为空(没有传参),并未奏效;
for (var i = 0; i <= 5; i++){ (function(){ setTimeout(function timer(){ let temp = new Date(); console.log(i + "----" + temp.toLocaleTimeString() + "." + temp.getMilliseconds()); }, i*1000) })(); if(i == 5){ var now = new Date(); console.log("for循环结束----"+now.toLocaleTimeString() + "." + now.getMilliseconds()); } }在立即执行函数中捕获一个变量
for (var i = 0; i <= 5; i++){ (function(){ var j = i; // IIFE有了自己的变量 setTimeout(function timer(){ let temp = new Date(); console.log(j + "----" + temp.toLocaleTimeString() + "." + temp.getMilliseconds()); }, j*1000) })(); if(i == 5){ var now = new Date(); console.log("for循环结束----"+now.toLocaleTimeString() + "." + now.getMilliseconds()); } } // for循环结束----下午8:14:28.915 // 0----下午8:14:28.916 // 1----下午8:14:29.916 // 2----下午8:14:30.916 // 3----下午8:14:31.916 // 4----下午8:14:32.916 // 5----下午8:14:33.916改进 1. 利用立即执行函数(IIFE)传参
利用立即执行函数为每个迭代都生成一个新的作用域,使得延迟函数的回调可以将新的作用域封闭在每个迭代内部;
for (var i = 0; i <= 5; i++){ (function(j){ setTimeout(function timer(){ let temp = new Date(); console.log(j + "----" + temp.toLocaleTimeString() + "." + temp.getMilliseconds()); }, j*1000) })(i); }2. 利用setTimeout给回调函数(callback)中传参,产生timer对for循环作用域的闭包
利用延迟函数向其回调函数中传参,为每个迭代中callback中生成新的作用域,使得延迟函数的回调可以将新的作用域封闭在每个迭代内部;
for (var i = 0; i <= 5; i++){ setTimeout(function timer(j){ let temp = new Date(); console.log(j + "----" + temp.toLocaleTimeString() + "." + temp.getMilliseconds()); }, i*1000, i); }3. 利用let声明劫持块作用域
本质:将一个块转换成了一个可以被关闭的作用域。
for(var i=0; i<5; i++){ let j = i;// 闭包的块作用域 setTimeout(function timer(){ console.log(j); }, j*1000); }4. 利用for循环头部的let声明
for循环头部的let声明的特殊行为:使得变量i在循环过程中不止被声明一次,每次迭代都会声明。
随后的每个迭代都会使用上一个迭代结束时的值来初始化这个变量。
for(let i=0; i<5; i++){ setTimeout(function timer(){ console.log(i); }, i*1000); }
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/99227.html
摘要:的分句会创建一个块作用域,其声明的变量仅在中有效。而闭包的神奇作用是阻止此事发生。依然持有对该作用域的引用,而这个引用就叫做闭包。当然,无论使用何种方式对函数类型的值进行传递,当函数在别处被调用时都可以观察到闭包。 date: 16.12.8 Thursday 第一章 作用域是什么 LHS:赋值操作的目标是谁? 比如: a = 2; RHS:谁是赋值操作的源头? 比如: conso...
摘要:比如程序会被分解为解析语法分析将词法单元流转换成一个由元素逐级嵌套所组成的代表了程序语法接口的书,又称抽象语法树。代码生成将抽象语法树转换为机器能够识别的指令。 showImg(https://segmentfault.com/img/remote/1460000009682106?w=640&h=280); 本文首发在我的个人博客:http://muyunyun.cn/ 《你不知道的...
摘要:注此读书笔记只记录本人原先不太理解的内容经过阅读你不知道的后的理解。作用域及闭包基础,代码运行的幕后工作者引擎及编译器。 注:此读书笔记只记录本人原先不太理解的内容经过阅读《你不知道的JS》后的理解。 作用域及闭包基础,JS代码运行的幕后工作者:引擎及编译器。引擎负责JS程序的编译及执行,编译器负责词法分析和代码生成。那么作用域就像一个容器,引擎及编译器都从这里提取东西。 ...
摘要:异步请求线程在在连接后是通过浏览器新开一个线程请求将检测到状态变更时,如果设置有回调函数,异步线程就产生状态变更事件,将这个回调再放入事件循环队列中。 基础:浏览器 -- 多进程,每个tab页独立一个浏览器渲染进程(浏览器内核) 每个浏览器渲染进程是多线程的,主要包括:GUI渲染线程 JS引擎线程 也称为JS内核,负责处理Javascript脚本程序。(例如V8引擎) JS引擎线程负...
摘要:但是如果非全局的变量如果被遮蔽了,无论如何都无法被访问到。但是如果引擎在代码中找到,就会完全不做任何优化。结构的分句中具有块级作用域。第四章提升编译器函数声明会被提升,而函数表达式不会被提升。 本书属于基础类书籍,会有比较多的基础知识,所以这里仅记录平常不怎么容易注意到的知识点,不会全记,供大家和自己翻阅; 上中下三本的读书笔记: 《你不知道的JavaScript》 (上) 读书笔记...
阅读 1666·2023-04-26 00:30
阅读 3144·2021-11-25 09:43
阅读 2867·2021-11-22 14:56
阅读 3182·2021-11-04 16:15
阅读 1137·2021-09-07 09:58
阅读 2012·2019-08-29 13:14
阅读 3101·2019-08-29 12:55
阅读 981·2019-08-29 10:57