html

<body>
<p>产品一</p>
<p>产品二</p>
<p>产品三</p>
<p>产品四</p>
<p>产品五</p>
</body>

js

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

上面代码点击每个p,输出都是5,因为这里的 i 是个引用。演示地址

要想输出对应的i,有以下方法:

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

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

演示地址

2、将变量 i 保存在匿名函数自身

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

演示地址

caller返回一个函数的引用,这个函数调用了当前的函数;

callee返回正在执行的函数本身的引用,它是arguments的一个属性

3.加一层闭包,i以函数参数形式传递给内层函数

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

演示地址

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

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

演示地址

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

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

演示地址

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

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

演示地址

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

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

演示地址

看了这篇文章,又想到用es5,es6的两个方法:

8、用es5 forEach函数

这里用forEach也行成了一个所谓的闭包,forEach里的执行函数也行成了一个闭包,每个执行体里,index都是一局部作用域,那为什么用Array.from呢,我们也可以用[].slice.call(node)我们类数组对象转化成真正的数组

function init() {
var pAry = document.getElementsByTagName("p");
//pAry = Array.from(pAry);
pAry = Array.prototype.slice.call(pAry);
pAry.forEach(function(currentItem,index){
currentItem.onclick = function(){
alert(index);
}
})
}
window.onload = init;

演示地址

9、用es6的let声明块级变量

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

演示地址

知乎关于这个问题也有一些回答

https://www.zhihu.com/question/33468703

JavaScript闭包 循环输出i的更多相关文章

  1. JavaScript利用闭包循环绑定事件

    我们经常在做前端面试题的时候,会遇到循环绑定事件后,输出打印结果,很多人总是搞不清楚,今天借此机会跟大家梳理一下闭包相关作用. 1.首先我们举一个简单的例子. html部分: <a href=& ...

  2. 从javascript的循环问题来看待闭包本质

    第一次接触这个问题还是在我刚开始学js的时候,当时就是一头雾水,时隔一年多了,突然又想起了这个问题,在这个春气盎然的周末,我就坐下来研究下并把结果和大家分享下: 先看代码:demo.html < ...

  3. JavaScript学习笔记-循环输出菱形,并可菱形自定义大小

    var Cen = 6;//定义菱形中部为第几行(起始值为0) //for循环输出菱形 document.write("<button onclick='xh()'>点我for循 ...

  4. JavaScript闭包深入解析

    for (var i=1; i<=5; i++) { setTimeout( function timer() { console.log( i ); }, i*1000 ); } --上面这段 ...

  5. JavaScript 闭包系列二(匿名函数及函数的闭包)

    一. 匿名函数 1. 函数的定义,可分为三种 1) 函数声明方式 function double(x) {     return 2*x; } 2)Function构造函数,把参数列表和函数体都作为字 ...

  6. JavaScript闭包模型

      JavaScript闭包模型 -----  [原创翻译]2016-09-01  09:32:22 < 一>  闭包并不神秘 本文利用JavaScript代码来阐述闭包,目的是为了使普通 ...

  7. JavaScript 闭包整合

    初遇闭包感觉很困惑,上网查看了些许介绍,有很多没看懂,就想先对能懂的东西整整 首先觉得要了解闭包,要先对一.JavaScript的变量作用域和作用域链有基本了解 1.变量的作用域分为:全局变量和局部变 ...

  8. JavaScript ——闭包理解

    昨天晚上听别人谈起闭包这个东西,虽然对js有一点了解但却丝毫没有印象,今天也没什么事就顺便研究了一下满足好奇宝宝.整合于网上的理解,记录一下. 一.闭包的作用域 要理解闭包,首先必须理解Javascr ...

  9. Javascript闭包的一些研究

    原文:Javascript闭包的一些研究 本文不谈闭包的概念,因为概念容易把人搞晕,本文希望通过几个鲜活的例子来探究闭包的性质,相信对理解闭包会有所帮助. 程序1 var f = (function( ...

随机推荐

  1. 多线程并发测试(apache ad)

    1.配置 ThreadPoolTaskExecutor bean   <?xml version="1.0" encoding="UTF-8"?> ...

  2. HDU1505-City Game(记忆化搜索)

    City Game http://acm.hdu.edu.cn/showproblem.php?pid=1505 Problem Description Bob is a strategy game ...

  3. python之时间处理time模块

    import time import datetime ''' print(time.time()) #返回当前系统时间戳 print(time.ctime()) #返回当前系统时间 print(ti ...

  4. android静默安装和智能安装(转)

    Android 静默安装和智能安装的实现方法 http://blog.csdn.net/fuchaosz/article/details/51852442 Android静默安装实现方案,仿360手机 ...

  5. D3DXCreateTexture

    HRESULT D3DXCreateTexture( __in LPDIRECT3DDEVICE9 pDevice, __in UINT Width, __in UINT Height, __in U ...

  6. 常用Style

    有些输入框什么的,字数限制什么的style,ceb为我们写好了.我感觉,每个app的style都是很有用的一个东西. <?xml version="1.0" encoding ...

  7. SXCPC2018 nucoj1999 占领城市

    #include <iostream> #include <cstring> #include <cstdio> #include <queue> us ...

  8. Leetcode 650.只有两个键的键盘

    只有两个键的键盘 最初在一个记事本上只有一个字符 'A'.你每次可以对这个记事本进行两种操作: Copy All (复制全部) : 你可以复制这个记事本中的所有字符(部分的复制是不允许的). Past ...

  9. nyoj 题目5 Binary String Matching

    Binary String Matching 时间限制:3000 ms  |  内存限制:65535 KB 难度:3   描述 Given two strings A and B, whose alp ...

  10. iOS设备唯一标识(可以用版)

    由于UDID和OpenUDID被禁用,系统自带的的识别唯一标识有两种 广告标示符(IDFA-identifierForIdentifier) 这是iOS 6中另外一个新的方法,advertisingI ...