用闭包解决 js 循环中函数变量暂存问题

需求:有一个数组,根据数组的值渲染对应的数字div,单击对应的div 在控制台打印对应的数字。如点击1,控制台打印1.

问题: 不管点击哪个值 打出来都是4

代码如下

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>testFor</title>
</head>
<body>
  <div id="container">
  </div>
  <script>
     var arr=[1,2,3,4];
     function clickNum(i) {
         console.log(i)
     }
     for(var i of arr){
         var iDiv=document.createElement(‘div‘);
         iDiv.addEventListener(‘click‘,function () {
             clickNum(i)
         });
         iDiv.innerText=i;
         var container=document.getElementById(‘container‘);
         container.appendChild(iDiv);
     }
  </script>
</body>
</html>

期望点击会打印出对应的数字,实际打出来的都是4

原因:

js函数在声明时,浏览器不会去查看函数内部逻辑。只有函数被使用时 才关心函数内部的变量引用。

如本例,只有在单击的时候 才会去触发clickNum函数,而此时循环已执行完毕,i已经变成了4。 所以不管哪个div的click 事件打印出来永远都是4。

解决思路:

1.因为我们需要用到即时的索引值i.所以 我们需要立即触发此函数。这里需要用到匿名函数。

2.有了匿名函数立即执行后,我们还需要将匿名函数中的变量暂存起来,留着点击的时候用,这里需要创建一个闭包。因为闭包的本质就是让内部的变量在函数执行完后也不被垃圾回收调。而是暂存起来。所以,如果需要在函数外部拿到函数内部的变量。或者想在将来拿到现在的变量 都只能通过闭包(我个人理解是这样的)

改后的代码

     for(var i of arr){
         var iDiv=document.createElement(‘div‘);
         iDiv.addEventListener(‘click‘,function (icopy) {
             return function () {
                clickNum(icopy)
             }
         }(i));
         iDiv.innerText=i;
         var container=document.getElementById(‘container‘);
         container.appendChild(iDiv);
     }

原文地址:https://www.cnblogs.com/ada-blog/p/11663091.html

时间: 2024-11-05 23:25:51

用闭包解决 js 循环中函数变量暂存问题的相关文章

Oracle中使用Table()函数解决For循环中不写成 in (l_idlist)形式的问题

转: Oracle中使用Table()函数解决For循环中不写成 in (l_idlist)形式的问题 在实际PL/SQL编程中,我们要对动态取出来的一组数据,进行For循环处理,其基本程序逻辑为: 1 2 3 4 5 6 7 8 9 10 11 12 create or replace procedure getidlist is   l_idlist varchar2(200); begin   l_idlist:='1,2,3,4';   for brrs in (select * fro

百度地图API详解之事件机制,function“闭包”解决for循环和监听器冲突的问题:

原文:百度地图API详解之事件机制,function"闭包"解决for循环和监听器冲突的问题: 百度地图API详解之事件机制 2011年07月26日 星期二 下午 04:06 和DOM编程里的事件模型一样,百度地图API也提供了类似的事件机制.本文介绍了事件监听的添加和移除方法,this指针和事件参数的使用以及绑定事件监听函数中涉及的闭包问题,最后分享了一个用来增强地图API事件机制的开源项目. 事件添加和移除 我们最简单的事件开始,下面的代码示例给map对象添加了click事件的监听

css文件中的样式类被覆盖,js文件中的变量未定义问题问题

Extjs控件中css样式表中的样式类部分被莫名其妙的覆盖 问题原因: 为什么呢? 因为在调用组件W的css样式时,我们自己写了css样式A,Ext组件又自带css样式B,A是我们用cls:'A'放进去.那么这个W到底是用两个样式重复的哪一个种呢? 这就要看css样式表的引入顺序了,如果先引入自己写的,再引入Ext自带的,那么浏览器先读自己写的css样式,然后再读Ext自带的样式.结果我们的自己写的css样式就被覆盖了. 解决办法: 这样就对了. js文件中的变量未定义问题 问题描述: read

Handlebars.js循环中索引(@index)使用技巧(访问父级索引)

使用Handlebars.js过程中,难免会使用循环,比如构造数据表格.而使用循环,又经常会用到索引,也就是获取当前循环到第几次了,一般会以这个为序号显示在页面上. Handlebars.js中获取循环索引很简单,只需在循环中使用{{@index}}即可. 1 <!DOCTYPE html> 2 <html> 3 <head> 4 <META http-equiv=Content-Type content="text/html; charset=utf-

使用javax.script包实现Java设置JS脚本中的变量

下面例子中,我们通过javax.script包ScriptEngine.put()方法设置JS脚本中的变量,JS把所有在线用户输出. package ajava.code.javase; import javax.script.ScriptEngineManager; import javax.script.ScriptEngine; import javax.script.ScriptException; import java.util.Date; public class AjavaAcc

彻底弄懂js循环中的闭包问题

第一次接触这个问题还是在我刚开始学js的时候,当时就是一头雾水,时隔一年多了,突然又想起了这个问题,在这个春气盎然的周末,我就坐下来研究下并把结果和大家分享下: 先看代码:demo.html<!DOCTYPE HTML> <html>  <head>   <meta charset="gbk"/>   <title>闭包循环问题</title>   <style type="text/css&quo

利用闭包解决for循环里onclick事件不能捕捉实时i值问题

问题描述 我们都知道,如果我们对于一组元素(相同的标签)同时进行onclick事件处理的时候(在需要获取到索引的时候),一般是写一个for循环,但是onclick是一个异步调用的,所以会带来一个问题,当我们触发这个事件的时候,我们能获取的i值是for完整执行完后i的值,而不能获取到代码顺序里i的值 首先看一段代码: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title

js文件中函数前加分号和感叹号是什么意思?

本文转自:http://blog.csdn.net/h_o_w_e/article/details/51388500 !function(){}();   !有什么用? 从语法上来开,JavaScript中分号表示语句结束,在开头加上,可能是为了压缩的时候和别的方法分割一下,表示一个新的语句开始.所以,如果在一个单独的JS文件中,开头的分号是没有任何意义的,可以删掉. 叹号是逻辑运算符,是"非"的意思,常见这种写法 if(!true){}:而将运算符加载函数定义的前面,则是将函数看做一

C++中函数变量布局小结

把布局作为一种信仰(Layout as Religion).                                                                                                                    --Steve McConnell(<代码大全>一书作者)        在 C 语言的早期版本中,由于规定变量的赋值必须在所有变量的声明之前,因此经常能看到如下形式的代码:           void