在下面的例子中,为什么点击所有的段落p输出都是5,而不是alert出对应的0,1,2,3,4。

 <html>
<head>
<meta charset="utf-8" />
<title>闭包演示</title>
<style type="text/css">
p {background:#ccc;}
</style>
<script type="text/javascript">
window.onload = function() {
var arr= document.getElementsByTagName("p");
for( var i=0; i<arr.length; i++ ) {
arr[i].onclick = function() {
alert(i);
}
}
}
</script>
</head>
<body>
<p>000</p>
<p>111</p>
<p>222</p>
<p>333</p>
<p>444</p>
</body>
</html>

原因是初学者并未理解JavaScript的闭包特性。通过element.onclick=function(){alert(i);}方式给元素添加 点击事件。响应函数function(){alert(i);}中的 i 并非每次循环时对应的 i(如0,1,2,3,4)而是循环后最后 i 的值5。 或者说循环时响应函数内并未能保存对应的值 i,而是最后一次i++的值5。

方法1:将变量 i 保存给在每个段落对象(p)上

  window.onload = function(){
var arr = document.getElementsByTagName('p');
for(var i=0; i<arr.length; i++){
arr[i].i= i; //或 arr[i].index = i;
arr[i].onclick = function(){
alert(this.i); //或alert(this.index);
}
}
}

方法2:加一层闭包,i 以函数参数形式传递给内层函数

window.onload = function () {
var arr= document.getElementsByTagName("p");
for( var i=0; i<pAry.length; i++ ) {
(function(arg){
arr[i].onclick = function() {
alert(arg);
};
})(i);//调用时参数
}
}

方法3:将变量 i 保存在匿名函数自身

 window.onload = function () {
var arr= document.getElementsByTagName("p");
for( var i=0; i<arr.length; i++ ) {
(arr[i].onclick = function() {
alert(arguments.callee.i);
}).i = i;
}
}

4、加一层闭包,i 以局部变量形式传递给内层函数

 1 window.onload = function () {
var arr= document.getElementsByTagName("p");
for( var i=0; i<arr.length; i++ ) {
(function () {
var temp = i;//调用时局部变量
arr[i].onclick = function() {
alert(temp);
}
})();
}
}

5、加一层闭包,返回一个函数作为响应事件(注意与2的细微区别)

 window.onload = function () {
var arr= document.getElementsByTagName("p");
for( var i=0; i<arr.length; i++ ) {
arr[i].onclick = function(arg) {
return function() {//返回一个函数
alert(arg);
}
}(i);
}
}

6、用Function实现,实际上每产生一个函数实例就会产生一个闭包

  window.onload = function() {
var arr= document.getElementsByTagName("p");
for( var i=0; i<arr.length; i++ ) {
arr[i].onclick = new Function("alert(" + i + ");"); //new一次就产生一个函数实例
}
}

7、用Function实现,注意与6的区别

 window.onload = function() {
var arr= document.getElementsByTagName("p");
for( var i=0; i<arr.length; i++ ) {
arr[i].onclick = Function('alert('+i+')');
}
}

JavaScript闭包示例的更多相关文章

  1. 一个简单的Javascript闭包示例

    //=====用闭包实现函数的Curry化===== //数字求和函数的函数生成器 function addGenerator( num ){ //返回一个简单的匿名函数,求两个数的和,其中第一个数字 ...

  2. JavaScript 闭包(个人理解)

    当function里嵌套function时,内部的function可以访问外部function里的变量.但这不是闭包 function foo(x) { var tmp = 3; function b ...

  3. 通过示例学习JavaScript闭包

    译者按: 在上一篇博客,我们通过实现一个计数器,了解了如何使用闭包(Closure),这篇博客将提供一些代码示例,帮助大家理解闭包. 原文: JavaScript Closures for Dummi ...

  4. [JavaScript闭包]Javascript闭包的判别,作用和示例

    闭包是JavaScript最重要的特性之一,也是全栈/前端/JS面试的考点. 那闭包究竟该如何理解呢? 如果不爱看文字,喜欢看视频.那本文配套讲解视频已发送到B站上供大家参考学习. 如果觉得有所收获, ...

  5. JavaScript学习总结——我所理解的JavaScript闭包

    一.闭包(Closure) 1.1.什么是闭包? 理解闭包概念: a.闭包是指有权限访问另一个函数作用域的变量的函数,创建闭包的常见方式就是在一个函数内部创建另一个函数,也就是创建一个内部函数,创建一 ...

  6. Javascript闭包和C#匿名函数对比分析

    C#中引入匿名函数,多少都是受到Javascript的闭包语法和面向函数编程语言的影响.人们发现,在表达式中直接编写函数代码是一种普遍存在的需求,这种语法将比那种必须在某个特定地方定义函数的方式灵活和 ...

  7. javascript 闭包最简单理解

    首先说3点与闭包有关系的东西. 一.变量的作用域 变量的作用域不难理解. 1.函数内部可以访问函数外部的变量,而函数外部不能访问函数内部的变量. 2.如果在函数内定义变量的时候,不加var,那么是全局 ...

  8. JavaScript闭包(一)——实现

    闭包的官方的解释是:一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分. 通俗点的说法是: 从理论角度:所有的函数.因为它们都在创建的时候就将上层上下文 ...

  9. 我所理解的JavaScript闭包

    目录 一.闭包(Closure) 1.1.什么是闭包? 1.2.为什么要用闭包(作用)? 1.2.1.保护函数内的变量安全. 1.2.2.通过访问外部变量,一个闭包可以暂时保存这些变量的上下文环境,当 ...

随机推荐

  1. DevExpress GridControl使用(转)

    DevExpress GridControl使用 (一)原汁原味的表格展示 Dev控件中的表格控件GridControl控件非常强大.不过,一些细枝末节的地方有时候用起来不好找挺讨厌的.使用过程中,多 ...

  2. Nginx 301重定向域名

    为何要使用301重定向 在网站建设中需要网页重定向的情况很多:如网页目录结构变动,网页重命名.网页的扩展名改变.网站域名改变等.如果不做重定向,用户的收藏和搜索引擎数据库中的旧地址只能让访客得到一个4 ...

  3. 【BZOJ】【2940】【POI2000】条纹

    博弈论 一开始想成S-Nim了……后来发现不一样= =石子是一定得取的,但是这个铺条纹就像Crosses and Crosses一样,是可以铺到中间,左右留下空隙但是对手无处可放的…… 所以就是两道题 ...

  4. git如何ignore

    今天新建了一个项目传到git上,但是每次编译都会有一些无用的文件生成,于是就编写了ignore.但是发现无用.因为你的文件已经上传到服务器了,再编写ignore就无用了,ignore的适用是文件没上传 ...

  5. [转载]C++ CString与int 互转

    1.CString 转 int      CString strtemp = "100";    int  intResult;    intResult= atoi(strtem ...

  6. 使用EF code first和asp.net mvc4遇到的问题总结

    最近使用EF code first和asp.net mvc4做项目,遇到些问题,记录一下. 一.EF code first 生成外键列问题. 一般情况下,都是先写一个int型外键id属性,然后写一个外 ...

  7. poj 2253 Frogger (最短路变种,连通图的最长边)

    题目 这里的dijsktra的变种代码是我看着自己打的,终于把代码和做法思路联系上了,也就是理解了算法——看来手跟着画一遍真的有助于理解. #define _CRT_SECURE_NO_WARNING ...

  8. D&F学数据结构系列——二叉堆

    二叉堆(binary heap) 二叉堆数据结构是一种数组对象,它可以被视为一棵完全二叉树.同二叉查找树一样,堆也有两个性质,即结构性和堆序性.对于数组中任意位置i上的元素,其左儿子在位置2i上,右儿 ...

  9. VirtualBox 给虚拟机绑定IP

    在VirtualBox中,有时候打开虚拟机,会出现Waiting for 60 seconds more for network configuration这种情况,从而使得开机变得很慢. 通过以下操 ...

  10. SpringMVC学习总结(五)——SpringMVC文件上传例子

    这是用的是SpringMVC-3.1.1.commons-fileupload-1.2.2和io-2.0.1 首先是web.xml <?xml version="1.0" e ...