问题再现

​ 最近开发中遇到一个问题,为什么每次输出都是5,而不是点击每个p,就alert出对应的1,2,3,4,5。

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>闭包演示</title>
</head>
<body>
<p>1</p>
<p>2</p>
<p>3</p>
<p>4</p>
<p>5</p>
<script type="text/javascript">
window.onload=function() {
var ps = document.getElementsByTagName("p");
for( var i=0; i<ps.length; i++ ) {
ps[i].onclick = function() {
alert(i);
}
}
}
</script>
</body>
</html>

此时点击任意p弹出的都是5

出现原因:js事件处理器在线程空闲时间不会运行,导致最后运行的时候输出的都是i最后的值,即:5


解决办法:使用闭包将变量i的值保护起来

//sava1:加一层闭包,i以函数参数形式传递给内层函数
for( var i=0; i<ps.length; i++ ) {
(function(arg){
ps[i].onclick = function() {
alert(arg);
};
})(i);//调用时参数
} //save2:加一层闭包,i以局部变量形式传递给内存函数
for( var i=0; i<ps.length; i++ ) {
(function () {
var temp = i;//调用时局部变量
ps[i].onclick = function() {
alert(temp);
}
})();
} //save3:加一层闭包,返回一个函数作为响应事件(注意与3的细微区别)
for( var i=0; i<ps.length; i++ ) {
ps[i].onclick = function(arg) {
return function() {//返回一个函数
alert(arg);
}
}(i);
} //save4:将变量 i 保存给在每个段落对象(p)上
for( var i=0; i<ps.length; i++ ) {
ps[i].i = i;
ps[i].onclick = function() {
alert(this.i);
}
} //save5:将变量 i 保存在匿名函数自身
for( var i=0; i<ps.length; i++ ) {
(ps[i].onclick = function() {
alert(arguments.callee.i);
}).i = i;
}
} //save6:用Function实现,实际上每产生一个函数实例就会产生一个闭包
for( var i=0; i<ps.length; i++ ) {
ps[i].onclick = new Function("alert(" + i + ");");//new一次就产生一个函数实例
} //save7:用Function实现,注意与6的区别
for( var i=0; i<ps.length; i++ ) {
ps[i].onclick = Function('alert('+i+')');
}

总结

在ECMAScript5和6中,var和let的作用域是不同的:var的作用域在函数上,let的作用域在块上,因此当有异步函数发生调用的时候,之前已经绑定好的点击事件会寻找在onload函数的i值,此时i值已经不是当初设定好的值,而是最后一次循环后的值,而使用let的话,那么在每次循环的时候就会在新的块上重新创建新的变量i,所以每次点击的i的值都会不同。

浅谈js for循环输出i为同一值的问题的更多相关文章

  1. 浅谈js for循环输出i为同一值的问题(闭包解决)

    1.最近开发中遇到一个问题,为什么每次输出都是5,而不是点击每个p,就alert出对应的1,2,3,4,5. <html> <head> <meta http-equiv ...

  2. 浅谈JS中的闭包

    浅谈JS中的闭包 在介绍闭包之前,我先介绍点JS的基础知识,下面的基础知识会充分的帮助你理解闭包.那么接下来先看下变量的作用域. 变量的作用域 变量共有两种,一种为全局变量,一种为局部变量.那么全局变 ...

  3. 浅谈 js 正则字面量 与 new RegExp 执行效率

    原文:浅谈 js 正则字面量 与 new RegExp 执行效率 前几天谈了正则匹配 js 字符串的问题:<js 正则学习小记之匹配字符串> 和 <js 正则学习小记之匹配字符串优化 ...

  4. 浅谈 js 字符串之神奇的转义

    原文:浅谈 js 字符串之神奇的转义 字符串在js里是非常常用的,但是你真的了解它么?翻阅<MDN String>就可以了解它的常见用法了,开门见山的就让你了解了字符串是怎么回事. 'st ...

  5. 浅谈 js 字符串 search 方法

    原文:浅谈 js 字符串 search 方法 这是一个很久以前的事情了,好像是安心兄弟在学习js的时候做的练习.具体记不清了,今天就来简单分析下 search 究竟是什么用的. 从字面意思理解,一个是 ...

  6. 浅谈JS中的!=、== 、!==、===的用法和区别 JS中Null与Undefined的区别 读取XML文件 获取路径的方式 C#中Cookie,Session,Application的用法与区别? c#反射 抽象工厂

    浅谈JS中的!=.== .!==.===的用法和区别   var num = 1;     var str = '1';     var test = 1;     test == num  //tr ...

  7. 浅谈JS中 var let const 变量声明

    浅谈JS中 var let const 变量声明 用var来声明变量会出现的问题: 1. 允许重复的变量声明:导致数据被覆盖 2. 变量提升:怪异的数据访问.闭包问题 3. 全局变量挂载到全局对象:全 ...

  8. 浅谈JS之AJAX

    0x00:什么是Ajax? Ajax是Asynchronous Javascript And Xml 的缩写(异步javascript及xml),Ajax是使用javascript在浏览器后台操作HT ...

  9. 浅谈 js 正则之 test 方法

    原文:浅谈 js 正则之 test 方法 其实我很少用这个,所以之前一直没注意这个问题,自从落叶那厮写了个变态的测试我才去看了下这东西.先来看个东西吧. var re = /\d/; console. ...

随机推荐

  1. Flutter沉浸式状态栏/AppBar导航栏/仿咸鱼底部凸起导航

    Flutter中如何实现沉浸式透明Statusbar状态栏效果? 如下图:状态栏是指android手机顶部显示手机状态信息的位置.android 自4.4开始新加入透明状态栏功能,状态栏可以自定义颜色 ...

  2. jq显示数据在kindeditor

    1,定义编辑器的变量为全局变量 2,将数据显示到kindeditor   在我自己这里_下划线相当于数据,也就是将数据显示在kindeditor 中的textarea中 3,jquery获取kinde ...

  3. MongoDB单机部署

    MongoDB单机部署 一.环境 系统:centos7.6 DB版本:mongodb-linux-x86_64-rhel62-4.2.1.tgz 官网地址:https://www.mongodb.co ...

  4. Java死锁编码及定位分析的demo

    死锁 死锁是什么 大学课程中的四个要素: (1)互斥(2)不可抢占(3)循环等待(4)请求保持 也就是下图所描述 产生死锁的主要原因 (1)系统资源不足(2)进程运行推进的顺序不合适(3)资源分配不当 ...

  5. 关于ptype_all和pypte_base中的pt_prev的说明[转]

    不知道原帖,我是从这里看到了,解决了迷惑我很久的疑问,抄过来. 看见noble_shi兄弟"关于net_rx_action函数的若干问题"贴中关于pt_prev的问题, 本来想在论 ...

  6. 多测试_linux_003_肖sir

    一.linux 介绍os 操作系统:windows,dos,android ,ios,unix ,linux linux系统:是一个免费,开源的操作系统,能多cpu,多用户,多线程的操作系统,比win ...

  7. java基础知识总结(续写)

    1.两个容易搞混的C盘文件夹 文件名 描述 Progrm Files 默认存储的64位软件 Progrm Files(x86) 默认存储32位软件 2.常用基础DOS命令(Windows+R打开命令) ...

  8. 工业级wifi模块

    工业级wifi模块 工业级wifi模块ZLSN7004是上海卓岚开发的一款高性能的Wifi.以太网转串口模块.与普通的wifi模块定位在低成本不同,7004定位在高稳定性.丰富功能,设计目标是面向对功 ...

  9. python面试题-django相关

    1.中间件 中间件一般做认证或批量请求处理,django中的中间件,其实是一个类,在请求和结束后,django会根据自己的规则在合适的时机执行中间件中相应的方法, 如请求过来 执行process_re ...

  10. 为什么大部分的程序员学编程,都会选择从C语言开始?

    软件行业经过几十年的发展,编程语言的种类已经越来越多了,而且很多新的编程语言已经在这个领域从开始的默默无闻到如今风风火火,整个编程语言朝着集成化方向发展,这样会导致很多的初学者选择上不像以前那么单一了 ...