网上搜到的关于该问题的一个方案是借一层函数避免问题
http://blog.csdn.net/victorn/article/details/3899261
不过到底还是很难理解.. 还有其他的方法去理解和解决吗?
更新: 我草草套了一层函数还好也避开了
回复内容:
很高兴有一个纯JS的问题。1,@杨咖啡 说的JS传参是传值不传址,其实不是这样的。JS中传参有两种方式:by value and by sharing.
像C,C++,Java,他们传参方式是by value 和 by reference。前者就是传值,后者是传址。而JS也是这样的,前者是传值,后者是传址。
By value是对于原始数据类型,例如int,char之类的;而By sharing 和By reference是对于高级数据结构,如Object,struct之类。我们可以想象到一个Object或是struct 不能仅仅通过传值进行传参。
一个简单的例子说明by reference和 by sharing的不同。
var bar;
var foo = bar;
bar = {'key' : 'value'};
console.log(foo , bar );
By sharing 中foo 是undefined , bar 是{'key' : 'value'}; 而By reference 则应该两者都是{'key' : 'value'}。
2. 其实LZ要理解这个问题,要明白JS中的作用域(scope)。
每个函数在创建完成时,他有3个重要的内置属性(property)也同时被创建。
{
AO //记录function内的变量,参数等信息
this // 就是在调用this.xx的时候的this
scope // 指向外层函数AO的一个链(在实现的时候,可能通过数组来实现).
}
JS中,大家经常讲的Scope其实是这样:SCOPE=AO+scope.
回到闭包的问题上:
如果我们这样写这个程序:
for(var i =0; i
}
可以得到inner function的SCOPE是这样的:
{
AO
this // 等于link[i]
scope // 指向window的记录,包括我们需要的变量i
}
这个for循环会立即执行完毕,那么当onclick触发时,inner function查找变量 i 时,会在AO+scope中找,AO中没有,scope中的变量i已经成为了link.length.
利用大家所说的闭包写这个程序:
//here is the window scope
for(var i =0; i
link[i].onclick = (function(i){ // outer function
return function(){ //inner function
alert(i);
};
})(i);
}
分析inner function的SCOPE:
{
AO // no important infomation
this // we don't care it.
scope //outer function and window scope
}
outer function的SCOPE
{
AO // 包含参数i
this // don't care it .
scope // window scope.
}
这时,如果inner function被触发,他会从自己的AO以及scope(outer function的AO 和 window scope)中找寻变量i. 可以看到outer function的AO中已经包含了i,而且对于这个for循环,会有对应有N个(function(){})() 被创建执行。所以每个inner function都有一个特定的包含了变量 i 的outer function。
这样就可以顺利输出0,1,2,3。。。。。。。。。
结论: 我们可以看到,闭包其实就是因为Scope产生的,所以,广义上来讲,所有函数都是闭包。
另外,这里面也包含了,this, function expression 和function declaration的区别,这里就不一一讲了。
3. 另外一种方法:
利用 dom onclick事件的bubble特性,也就是@xiiiiiin所讲的弄个代理。
在link dom节点的父节点上定义onclick事件监听。参数为e(其他的名字也可以,但要有参数)。 这样我们通过e.target就可以知道是那个子节点被click了,也可以做相应的处理。
这是一个比较好的方法。(闭包有时会产生内存泄漏)。
大概就说这么多吧,还要上班呢。希望对LZ有用。如果哪里错了,也请多多批评指正。 我觉得最好的方式就是通过包装一层函数来解决。
将原来的
alink.onclick = function(){alert(i)};
改成:
(function(i) { alink.onclick = function(){alert(i)}; })(i);
我觉得这是最好的方法了,js 中只有 function 才会划分作用域(和 python 有点像),if/else、for 循环都不会划分作用域,所以原来的方式六次循环引用的都是同一个变量 i,由于闭包绑定到 function 中去。
现在包装了一层之后,i 被传递到内层的匿名函数 local 作用域中去,所以六次循环都会建立独立的 i (因为是六个不同的作用域)。 不看那文章你的问题还真难理解。
你把参数进去嘛:
alink.onclick = (function(i){
return function(){
alert(i);
};
})(i);
另外我不喜欢 onxxx 属性。
PS: 知乎用富文本编辑器弄得我贴代码都麻烦,另外,答案的后部分第 N 次消失看不到了。
这跟JS函数的传参方式和事件的赋值方式有关。
1、JS函数传参是传值不传址的。
2、onclick的值应该给一个函数声明,事件触发时只会传一个event参数给声明的函数。
如果在循环中使用alink[i].onclick = function() { alert(i); };
i 不是这个匿名函数的参数,是传址进去的,当onclick事件触发的时候循环已经结束了,i 已经是最后一个值了。
如果声明 function(i) { alert(i); }
那这个 i 就指代了 event,这时候事件触发的时候只会弹出触发的事件名。
而使用alink[i].onclick = (function(_i) { return function() { alert(_i); } })(i);
这里是执行外层的匿名函数,返回内层的这个匿名函数传给onclick。
这里注意外层函数是立即执行的,带一个参数,是我们传给它的,而不是事件触发器。
内层函数是不带参数的,事件执行时触发器会传给它一个event值。
对循环中的每一个 i 都会生成一个匿名函数,i 作为生成的匿名函数的参数,是传值的。
相当于循环中当 i = 2 的时候,生成了这样一个函数:function() { alert(2); }; 赋值给了alink[2].onclick,即 alink[2].onclick = function() { alert(2); };
这才是我们想要的。
PS:闭包只是个手法,而不是解决问题的核心所在。
这种手法跟下面的方法是等价的,而下面并没有用闭包。
var al = function(param) {
return function() {
alert(param);
}
}
循环中alink[i].onlick = al(i); 呃……这例子,更偏向于变量作用域的问题吧 重新思考了一下这个问题,它的关键在于弄清JavaScript变量作用域和作用域链,前面的回答似乎都没有解释清楚。
《JavaScript: The Good Parts》中提到了这个问题,看这个例子:
// BAD EXAMPLE
var addActions = function (nodes) {
for (var i = 0; i nodes[i].onclick = function (e) {
alert(i);
};
}
};
// END BAD EXAMPLE
解释是这样的:
函数的本意是给每个事件处理器不同的 i 。但它未能达到目的,因为事件处理器函数绑定了 i 本身,而不是函数在构造时的变量 i 的值。
之所以是这样的,看过《JavaScript: The Definitive Guide》就会明白:
所有的JavaScript函数都是闭包:它们都是对象,都关联到作用域链。每次调用JavaScript函数的时候,都会为之创建一个新的对象来保存局部变量,并把这个对象添加至作用域链中(简单理解:作用域链就是对象列表)。
这个糟糕的例子中function (e) { alert(i); }都会在同一个函数调用中定义,因此它们共享变量 i 。也就是说它们的作用域链里面的 i 都是同一个 i 。即关联到闭包的作用域链都是“活动的”。
《JavaScript: The Good Parts》当然也给出了解决方案:
var addActions = function (nodes) {
var helper = function (i) {
return function (e) {
alert(i);
};
};
for (var i = 0; i nodes[i].onclick = helper(i);
}
};
解释: 在循环之外创建一个辅助函数,而不是在循环中创建函数。 看一下这篇文章就全部都清楚了 JavaScript的执行上下文 在这里我觉得排名第一的回答太过于晦涩,一般人根本看不懂。
在这里我提出一个比较有意思的猜想,
//————————————————————————————————————————
//贴出代码
http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
http://www.w3.org/1999/xhtml">
<script><br>var oUl1=document.getElementById('ul1');<br>//alert(oUl1);<br>var aLi=document.getElementsByTagName('li');<br>var length=aLi.length;<br>for(var i=0;i<length;i++)<br>{<br><br> aLi[i].onclick=(function (index){<br> var y=i;<br> return function (){<br><br> // alert(index);<br> alert(y);<br> }; <br> }<br> )(i);<br>}<br>//提出猜想,引用次数加一变成2不再有跨作用域问题<br><br>//猜测正确<br></script>

Springboot内置tomcat禁止不安全HTTP方法1、在tomcat的web.xml中可以配置如下内容让tomcat禁止不安全的HTTP方法/*PUTDELETEHEADOPTIONSTRACEBASIC2、Springboot使用内置tomcat没有web.xml配置文件,可以通过以下配置进行,简单来说就是要注入到Spring容器中@ConfigurationpublicclassTomcatConfig{@BeanpublicEmbeddedServletContainerFacto

1.HttpURLConnection使用JDK原生提供的net,无需其他jar包,代码如下:importcom.alibaba.fastjson.JSON;importjava.io.BufferedReader;importjava.io.InputStream;importjava.io.InputStreamReader;importjava.io.OutputStream;importjava.net.HttpURLConnection;

一、前言#ssl写在443端口后面。这样http和https的链接都可以用listen443sslhttp2default_server;server_namechat.chengxinsong.cn;#hsts的合理使用,max-age表明hsts在浏览器中的缓存时间,includesubdomainscam参数指定应该在所有子域上启用hsts,preload参数表示预加载,通过strict-transport-security:max-age=0将缓存设置为0可以撤销hstsadd_head

随着互联网的不断发展和改善,Web服务器在速度和性能上的需求也越来越高。为了满足这样的需求,Nginx已经成功地掌握了HTTP2协议并将其融入其服务器的性能中。HTTP2协议要比早期的HTTP协议更加高效,但同时也存在着特定的安全问题。本文将为您详细介绍如何进行Nginx的HTTP2协议优化和安全设置。一、Nginx的HTTP2协议优化1.启用HTTP2在N

httpkeepalive在http早期,每个http请求都要求打开一个tpcsocket连接,并且使用一次之后就断开这个tcp连接。使用keep-alive可以改善这种状态,即在一次tcp连接中可以持续发送多份数据而不会断开连接。通过使用keep-alive机制,可以减少tcp连接建立次数,也意味着可以减少time_wait状态连接,以此提高性能和提高httpd服务器的吞吐率(更少的tcp连接意味着更少的系统内核调用,socket的accept()和close()调用)。但是,keep-ali

一、urllib概述:urllib是Python中请求url连接的官方标准库,就是你安装了python,这个库就已经可以直接使用了,基本上涵盖了基础的网络请求功能。在Python2中主要为urllib和urllib2,在Python3中整合成了urllib。Python3.x中将urllib2合并到了urllib,之后此包分成了以下四个模块:urllib.request:它是最基本的http请求模块,用来模拟发送请求urllib.error:异常处理模块,如果出现错误可以捕获这些异常urllib

被动检查对于被动健康检查,nginx和nginxplus会在事件发生时对其进行监控,并尝试恢复失败的连接。如果仍然无法恢复正常,nginx开源版和nginxplus会将服务器标记为不可用,并暂时停止向其发送请求,直到它再次标记为活动状态。上游服务器标记为不可用的条件是为每个上游服务器定义的,其中包含块中server指令的参数upstream:fail_timeout-设置服务器标记为不可用时必须进行多次失败尝试的时间,以及服务器标记为不可用的时间(默认为10秒)。max_fails-设置在fai

一、概述在实际开发过程中,我们经常需要调用对方提供的接口或测试自己写的接口是否合适。很多项目都会封装规定好本身项目的接口规范,所以大多数需要去调用对方提供的接口或第三方接口(短信、天气等)。在Java项目中调用第三方接口的方式有:1、通过JDK网络类Java.net.HttpURLConnection;2、通过common封装好的HttpClient;3、通过Apache封装好的CloseableHttpClient;4、通过SpringBoot-RestTemplate;二、Java调用第三方


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

Safe Exam Browser
Safe Exam Browser is a secure browser environment for taking online exams securely. This software turns any computer into a secure workstation. It controls access to any utility and prevents students from using unauthorized resources.

PhpStorm Mac version
The latest (2018.2.1) professional PHP integrated development tool

MinGW - Minimalist GNU for Windows
This project is in the process of being migrated to osdn.net/projects/mingw, you can continue to follow us there. MinGW: A native Windows port of the GNU Compiler Collection (GCC), freely distributable import libraries and header files for building native Windows applications; includes extensions to the MSVC runtime to support C99 functionality. All MinGW software can run on 64-bit Windows platforms.

WebStorm Mac version
Useful JavaScript development tools

mPDF
mPDF is a PHP library that can generate PDF files from UTF-8 encoded HTML. The original author, Ian Back, wrote mPDF to output PDF files "on the fly" from his website and handle different languages. It is slower than original scripts like HTML2FPDF and produces larger files when using Unicode fonts, but supports CSS styles etc. and has a lot of enhancements. Supports almost all languages, including RTL (Arabic and Hebrew) and CJK (Chinese, Japanese and Korean). Supports nested block-level elements (such as P, DIV),
