关于在for循环中绑定事件打印变量i是最后一次。
其实函数引用的外部变量都是最后一次的值。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
#box{
width:100px;
height:100px;
background-color:pink;
}
</style>
<script src="index.js"></script>
</head>
<body>
<div id="box"></div>
</body>
</html>
///////////////////////////////js代码//////////////////////////
window.onload = function(){
var box = document.getElementById("box");
var num = 0;
function a(){
console.log(num);
} box.onclick = function(){
num ++;
a(); // 1,2,3,4....每次单击都会加1,说明函数引用外部变量是引用那个变量的最后一次的值。
}
}
再来看一个例子:
window.onload = function(){
var box = document.getElementById("box");
var num = 0;
for(var i=0;i<10;i++){
box.onclick = function(){
console.log(i); //总是打印10
}
}
}
如果你知道作用域链就好办多了,在这个函数里面的i其实引用的是最后一次i的值,为什么不是1,2,3,4...呢?因为在你for循环的时候,你并没有执行这个函数,你这个函数是在你点击的时候才执行的,当执行这个函数的时候,它发现它自己没有这个变量i,于是向它的作用域链中查找这个变量i,因为当你单击这个box的时候已经for循环完了,所以储存在作用域链里面的i的值就是10,最后就打印出来10了。
for(var i=0;i<10;i++){
function a(){
console.log(i);
}
a(); //1,2,3,4,5....
}
为什么这样就可以呢?因为你在循环变量i的时候已经执行了函数a,自然变量i是什么就打印出来什么。
现在知道为什么绑定事件的时候打印出来的是最后一次的for循环的值了吧。
如果你知道理解这段话,我相信你知道怎么去解决这个问题。
解决方法1:让这个函数直接执行。
解决方法2:将每次for循环中的变量i保存到某个地方。
方法1:
window.onload = function(){
var box = document.getElementById("box");
var num = 0;
for(var i=0;i<10;i++){
box.onclick = a();
function a(){
console.log(i); //1,2,3,4.....
}
}
}
虽然这样可以打印出每次的变量i的值,但是我们没有点击box的时候它已经执行完了,直接无视了点击事件,也就是说这个点击事件已经可有可无了,所以我们用这种方法在绑定事件中就显得不那么可用了,那我们用方法2试试吧。
方法2:
window.onload = function(){
var div = document.getElementsByTagName("div");
var num = 0;
for(var i=0;i<div.length;i++){
(function(i){
div[i].onclick = function(){
console.log(i);
}
})(i)
}
}
成功打印每个i的值,原理就是通过自执行函数,并且将变量i保存到这个自执行函数的参数中。如果你不知道什么是自执行函数可以看初识js中的闭包这一节。
你们我们应该选择那种方法呢?当然看你的情况了,如果没有关于绑定事件的话,就是说让这个函数直接执行的,那就用方法1,否则用方法2,另外方法2通用,但是因为里面的i会一直保存到内存中比较消耗性能的原因,所以在没有必要的情况下尽量不要用这种方式,其实还可以将i绑定到元素的属性上。
关于在for循环中绑定事件打印变量i是最后一次。的更多相关文章
- JQuery在循环中绑定事件的问题详解
JQuery在循环中绑定事件的问题详解 有个页面上需要N个DOM,每个DOM里面的元素ID都要以数字结尾,比如说 ? 1 2 3 <input type="text" nam ...
- vue 如何在循环中绑定v-model
vue 如何在循环中绑定v-model 我现在有这么一个需求,页面上有多项输入框,但是具体有多少项,我也不知道,它是通过"新增一项"按钮点击事件,点击一下,就新增一项:如下图这个样 ...
- jQuery中绑定事件bind() on() live() one()的异同
jQuery中绑定事件的四种方法,他们可以同时绑定一个或多个事件 bind()-------------------------版本号小于3.0(在Jquery3.0中已经移除,相应unbind()也 ...
- jQuery中绑定事件的几种方法
以click事件为例,jQuery中绑定事件有三种方法: (1)target.click(function(){}); (2)target.bind("click",functi ...
- 不使用jquery情况下循环添加绑定事件方法
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- JavaScript中绑定事件监听函数的通用方法addEvent() 和 事件绑定之bindEvent()与 unBindEvent()函数
下面绑定事件的代码,进行了兼容性处理,能够被所有浏览器支持: function addEvent(obj,type,handle){ try{ // Chrome.FireFox.Opera.Safa ...
- JQuery中绑定事件(bind())和移除事件(unbind())
有时候事件执行完了,想取消事件的效果可以通过一定的办法来处理.比如bind()(绑定事件)和unbind()(移除通过bind()方法添加的事件)方法来移除事件的效果. 比如下面的一个案例: 复制代码 ...
- JS中绑定事件顺序(事件冒泡与事件捕获区别)
在JS中,绑定的事件默认的执行时间是在冒泡阶段执行,而非在捕获阶段(重要),这也是为什么当父类和子类都绑定了某个事件,会先调用子类绑定的事件,后调用父类的事件.直接看下面实例 <!Doctype ...
- Jquery中绑定事件的异同
谈论jquery中bind(),live(),delegate(),on()绑定事件方式 1. Bind() $(selector).bind(event,data,function) Event:必 ...
随机推荐
- plsql无法连接64位oracle数据库的解决方法(图文解说)
oracle11g下载页面:http://www.oracle.com/technetwork/database/enterprise-edition/downloads/index.html,找到适 ...
- Comet技术详解:基于HTTP长连接的Web端实时通信技术
前言 一般来说,Web端即时通讯技术因受限于浏览器的设计限制,一直以来实现起来并不容易,主流的Web端即时通讯方案大致有4种:传统Ajax短轮询.Comet技术.WebSocket技术.SSE(Ser ...
- 地图源改变之后mxd文件打开很慢的问题
在使用ArcGIS开发电子地图程序时,有时候需要更换服务器地址,这时打开MXD文件就会非常慢,一直没有找到有效的方法,下面是从网上搜到的方法,还没有验证,下次再碰到这个问题的时候,验证一下: (以下方 ...
- Python:将utf-8格式的文件转换成gbk格式的文件
需求:将utf-8格式的文件转换成gbk格式的文件 实现代码如下: def ReadFile(filePath,encoding="utf-8"): with codecs.ope ...
- mysql in 排序
SELECT * FROM my_table WHERE id IN (30, 20, 80, 40) ORDER BY FIELD(id, 30, 20, 80, 40);
- icmp,tcp,traceroute,ping,iptables
有东莞的监控主机到北京BGP出问题了: 报警短信疯狂发送: 找东莞IDC和北京BGP服务商协查: 有个奇怪的问题:北京到东莞trcaceroute都有路由信息 东莞143段到北京全无路由信息:但,东莞 ...
- HL AsySocket 服务开发框架 - 业务逻辑层
一 概述 Socket服务只是提供一个网络传输服务. 业务逻辑层在整体架构中的位置在那里呢,如图: 网络层将解包后的消息包抛至业务逻辑层,业务逻辑层收到消息包后,解析消息类型,然后转入相应的处理流程处 ...
- MSSql使用SQL语句快速查看表对的就说明,及表字段描述及字段类型
--表描述 SELECT tbs.name 表名,ds.value 描述 FROM sys.extended_properties ds LEFT JOIN sysobjects tbs ON ds. ...
- Solr 5.x集成中文分词word,mmseg4j
使用标准分词器,如图: 使用word分词器 下载word-1.3.jar,注意solr的版本和word分词的版本 将文件word-1.3.jar拷贝至文件夹C:\workspace\Tomcat7.0 ...
- jeos没有消亡,但看 debian 的 netinst .iso格式,那就是jeos的系统!
曾经ubuntu推出专供轻量硬件(如虚拟机)方式的just os格式的.iso [小巧.轻量.快速.干净] 但在 ubuntu 8.04后 再也没有继续 ...... 可惜 不曾想,ubuntu的老爸 ...