JavaScript闭包 循环输出i
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的更多相关文章
- JavaScript利用闭包循环绑定事件
我们经常在做前端面试题的时候,会遇到循环绑定事件后,输出打印结果,很多人总是搞不清楚,今天借此机会跟大家梳理一下闭包相关作用. 1.首先我们举一个简单的例子. html部分: <a href=& ...
- 从javascript的循环问题来看待闭包本质
第一次接触这个问题还是在我刚开始学js的时候,当时就是一头雾水,时隔一年多了,突然又想起了这个问题,在这个春气盎然的周末,我就坐下来研究下并把结果和大家分享下: 先看代码:demo.html < ...
- JavaScript学习笔记-循环输出菱形,并可菱形自定义大小
var Cen = 6;//定义菱形中部为第几行(起始值为0) //for循环输出菱形 document.write("<button onclick='xh()'>点我for循 ...
- JavaScript闭包深入解析
for (var i=1; i<=5; i++) { setTimeout( function timer() { console.log( i ); }, i*1000 ); } --上面这段 ...
- JavaScript 闭包系列二(匿名函数及函数的闭包)
一. 匿名函数 1. 函数的定义,可分为三种 1) 函数声明方式 function double(x) { return 2*x; } 2)Function构造函数,把参数列表和函数体都作为字 ...
- JavaScript闭包模型
JavaScript闭包模型 ----- [原创翻译]2016-09-01 09:32:22 < 一> 闭包并不神秘 本文利用JavaScript代码来阐述闭包,目的是为了使普通 ...
- JavaScript 闭包整合
初遇闭包感觉很困惑,上网查看了些许介绍,有很多没看懂,就想先对能懂的东西整整 首先觉得要了解闭包,要先对一.JavaScript的变量作用域和作用域链有基本了解 1.变量的作用域分为:全局变量和局部变 ...
- JavaScript ——闭包理解
昨天晚上听别人谈起闭包这个东西,虽然对js有一点了解但却丝毫没有印象,今天也没什么事就顺便研究了一下满足好奇宝宝.整合于网上的理解,记录一下. 一.闭包的作用域 要理解闭包,首先必须理解Javascr ...
- Javascript闭包的一些研究
原文:Javascript闭包的一些研究 本文不谈闭包的概念,因为概念容易把人搞晕,本文希望通过几个鲜活的例子来探究闭包的性质,相信对理解闭包会有所帮助. 程序1 var f = (function( ...
随机推荐
- 自动发现项目中的URL,django1版本和django2版本
一.django 1 版本 routers.py import re from collections import OrderedDict from django.conf import setti ...
- g++编译器的使用(转载)
关于g++ g++ 是GNU组织开发出的编译器软件集合(GCC)下的一个C++编译器.它是Unix 和 Linux 系统下标配的 基于命令行的 C++编译器.如果你的系统是Windows,可以按照 ...
- P1309 瑞士轮
题目背景 在双人对决的竞技性比赛,如乒乓球.羽毛球.国际象棋中,最常见的赛制是淘汰赛和循环赛.前者的特点是比赛场数少,每场都紧张刺激,但偶然性较高.后者的特点是较为公平,偶然性较低,但比赛过程往往十分 ...
- 菜鸟学Linux - Linux文件属性
在Linux中,文件的属性是一个很重要的概念,用户或者用户组对一个文件所拥有的权限,都可以从文件的属性得知. 我们可以通过ls -al命令,列出某个文件夹下面的所有文件(包括以.开头的隐藏文件).下面 ...
- laravel5.2总结--本地化以及常量的使用
1.本地化 Laravel 的本地化功能提供方便的方法来获取多语言的字符串,让你的网站可以简单的支持多语言. 语言包存放在 resources/lang 文件夹的文件里.每一个子目录应该对应一种语言 ...
- 设计模式之第19章-中介者模式(Java实现)
设计模式之第19章-中介者模式(Java实现) “测试妹纸找你,你的代码出问题了.”“美工妹纸让你看看界面怎么样.”身为程序员总要和各种人打交道,但是如果再分为前端.后端工程师的话,那么关系就会错综复 ...
- 纯js国际化(i18n)
i18n,是internationalization单词的简写,中间18个字符略去,简称i18n,意图就是实现国际化,方便产品在不同的场景下使用 目标:可以点击切换语言或者ChangeLanguage ...
- 为什么对多线程编程这么怕?pthread,sem,mutex,process
转自http://blog.chinaunix.net/uid-20788636-id-1841334.html 1.线程创建和退出创建线程实际上就是确定调用该线程函数的入口点,这里通常使用的函数是p ...
- .net学习笔记--设计模式
设计模式都有哪些? 按照GOF提出,23种,按照目的分为:创建型(creational).结构性(structural).行为型(behavioral). 一.创建型: 1.Singleton 单例模 ...
- jira从windows迁移到linux
说明:迁移的就是 jira安装路径/atlassian/jira/atlassian-jira/WEB-INF/classes/jira-application.properties文件中的jira_ ...