概念:
封闭了外部函数作用域中变量的内部函数,并且返回该内部函数,该变量称为自由变量,也可以叫做闭包变量. 即便返回该外部函数,由于内部函数的间接引用该变量,当GC检查没有相关对象引用它时,就会释放该资源.//(1)
function (n) {
alert(n);
} (3); //没有效果
//(2)
(function (n) {
alert(n);
})(3); //会弹出3
//(3)
var b = function (n) {
alert(n);
} (3); //也会弹出3
//(4)
var b1 = function (n) {
alert(n);
}
b1(3); //也会弹出3
/*从上面代码中我可以得出
1.(1)和(2)的区别在于(1)没有执行,(2)执行啦
2.()表示让匿名函数立刻执行
*//*
通过下面代码Result1和Result2输出的结果分别是什么了.
结果肯定是不一样的
Method1:输出的是:1-9
Method2:输出的是:9个10
为什么会这样了.
你可以考虑刚才的开胃小菜中的Demo.
下面我们来看下Method1中的
(function (m) {
return m;
})(i);
这个匿名函数返回的是经过运算结果的值,然后赋给数组
接下来我们看下Method2中的
array[j] = function () {
return j;
};
此时数组获取的时该函数的引用,该函数并没有执行
*/
function CreateArray1() {
var array = new Array();
for (var i = 0; i < 10; i++) {
//区别
array[i] = (function (m) {
return m;
})(i);
}
return array;
}
var results1 = CreateArray1();
document.write("Method1 Results:<br/>");
for (var i = 0; i < results1.length; i++) {
document.write(results1[i]+"<br/>");
}
document.write("------------------------<br/>");
document.write("Method2 Results:<br/>");
function CreateArray2() {
var array = new Array();
for (var j = 0; j < 10; j++) {
//区别
array[j] = function () {
return j;
};
}
return array;
}
var results2 = CreateArray2();
for (var i = 0; i < results2.length; i++) {
document.write(results2[i]() + "<br/>");
}
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script type="text/javascript">
/*
当我点击例子1,例子2,例子3的时候 分别弹出1,2,3
代码如下:
但是下面的代码没有得到我想要的效果,而是点击所有的"例子"都是4.
这个原因就是闭包造成的.每个点击onclick引用的函数都是alert()
当真个循环结束的时候,alert()函数返回的值是最大值.
怎么解决这个问题了
看func2()
//怎么理解这个话(function (n) { return function () { alert(n) }; })(v);
立刻执行当前函数,当前例子onclick引用的函数就是function () { alert(n) },n的值就是当前v的值
*/
function func1() {
var v;
for (var i = 1; i < 5; i++) {
v = i;
document.getElementById('closureExample' + v).onclick = function () { alert(v) };
}
}
function func2() {
var v;
for (var i = 1; i < 5; i++) {
v = i;
document.getElementById('closureExample' + v).onclick = (function (n) { return function () { alert(n) }; })(v);
}
}
window.onload = function () {
//func1();
func2();
}
</script>
</head>
<body>
<a href="#" id="closureExample1">例子1</a>
<a href="#" id="closureExample2">例子2</a>
<a href="#" id="closureExample3">例子3</a>
<a href="#" id="closureExample4">例子4</a>
</body>
</html>
封闭了外部函数作用域中变量的内部函数,并且返回该内部函数,该变量称为自由变量,也可以叫做闭包变量. 即便返回该外部函数,由于内部函数的间接引用该变量,当GC检查没有相关对象引用它时,就会释放该资源.//(1)
function (n) {
alert(n);
} (3); //没有效果
//(2)
(function (n) {
alert(n);
})(3); //会弹出3
//(3)
var b = function (n) {
alert(n);
} (3); //也会弹出3
//(4)
var b1 = function (n) {
alert(n);
}
b1(3); //也会弹出3
/*从上面代码中我可以得出
1.(1)和(2)的区别在于(1)没有执行,(2)执行啦
2.()表示让匿名函数立刻执行
*//*
通过下面代码Result1和Result2输出的结果分别是什么了.
结果肯定是不一样的
Method1:输出的是:1-9
Method2:输出的是:9个10
为什么会这样了.
你可以考虑刚才的开胃小菜中的Demo.
下面我们来看下Method1中的
(function (m) {
return m;
})(i);
这个匿名函数返回的是经过运算结果的值,然后赋给数组
接下来我们看下Method2中的
array[j] = function () {
return j;
};
此时数组获取的时该函数的引用,该函数并没有执行
*/
function CreateArray1() {
var array = new Array();
for (var i = 0; i < 10; i++) {
//区别
array[i] = (function (m) {
return m;
})(i);
}
return array;
}
var results1 = CreateArray1();
document.write("Method1 Results:<br/>");
for (var i = 0; i < results1.length; i++) {
document.write(results1[i]+"<br/>");
}
document.write("------------------------<br/>");
document.write("Method2 Results:<br/>");
function CreateArray2() {
var array = new Array();
for (var j = 0; j < 10; j++) {
//区别
array[j] = function () {
return j;
};
}
return array;
}
var results2 = CreateArray2();
for (var i = 0; i < results2.length; i++) {
document.write(results2[i]() + "<br/>");
}
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script type="text/javascript">
/*
当我点击例子1,例子2,例子3的时候 分别弹出1,2,3
代码如下:
但是下面的代码没有得到我想要的效果,而是点击所有的"例子"都是4.
这个原因就是闭包造成的.每个点击onclick引用的函数都是alert()
当真个循环结束的时候,alert()函数返回的值是最大值.
怎么解决这个问题了
看func2()
//怎么理解这个话(function (n) { return function () { alert(n) }; })(v);
立刻执行当前函数,当前例子onclick引用的函数就是function () { alert(n) },n的值就是当前v的值
*/
function func1() {
var v;
for (var i = 1; i < 5; i++) {
v = i;
document.getElementById('closureExample' + v).onclick = function () { alert(v) };
}
}
function func2() {
var v;
for (var i = 1; i < 5; i++) {
v = i;
document.getElementById('closureExample' + v).onclick = (function (n) { return function () { alert(n) }; })(v);
}
}
window.onload = function () {
//func1();
func2();
}
</script>
</head>
<body>
<a href="#" id="closureExample1">例子1</a>
<a href="#" id="closureExample2">例子2</a>
<a href="#" id="closureExample3">例子3</a>
<a href="#" id="closureExample4">例子4</a>
</body>
</html>
http://blog.csdn.net/ws_hgo/article/details/6892994
<body>
<a href="#" id="closureExample1">例子1</a>
<a href="#" id="closureExample2">例子2</a>
<a href="#" id="closureExample3">例子3</a>
<a href="#" id="closureExample4">例子4</a>
<script type="text/javascript">
function func2() {
var aCollection = document.getElementsByTagName("a");
for(var i=0;i<aCollection.length;i++){
aCollection[i].onclick=(function(n){
return function(){alert(n+1);}
})(i)
}
}
func2();
</script>
</body>
Thanks
你和我的代码 没有多大区别 都是一个意思
(function (n) {
alert(n);
})(3); 函数加()是原型的意思吗?
var object={
function one() {},
function two() {}
}
直观一下var a ="eeeee"
a.length"eeeee".length//出错
("eeeee").length //木问题
function aa(){
alert(1)
}//我要执行他?
function aa(){
alert(1)
}()//???出错
(function aa(){
alert(i)
})()//木问题总的来说“()”表达式运算
http://www.cnblogs.com/snandy/archive/2011/03/08/1977112.html
传送们看下
我理解的函数加()表示一个匿名函数指向里面的函数
(3),传入参数3并调用匿名函数,相当于下面方式的内联写法,只不过直接省去了中间变量
var b1 = function (n) {
alert(n);
}
b1(3);
声明变量的用法跟C#中的Action<T>使用上是一样的,但C#委托暂时不支持委托的内联调用
最后那段代码,func1的理解不对。之所以会出现错误的答案,不是因为闭包,而是没有用闭包造成的。js是运行时绑定。在事件句柄运行的时候,外部循环早就结束。所以会是4。
function start1(a){} // 私有方法
function start2(a){}
var count = 0; // 私有变量
var a = {
start : function(){
count ++;
start1();
start2();
}
}; $g.a = a; // 挂到$g上,作用域外访问的唯一途径})(window);我一般这么用
在c#中,this始终指向最外层的类的实例,对吧?
比如class A{
private A self = this;
public void a(){
object b = new Action(delegate(){
this.self == this; // 这里的this就是self,对吧
});
}
}
var btn = document.getElementById("btn");
for(var i=0; i<10; i++){
btn.onclick = function(i){
return function(){
alert(i)
}
}(i)
}
现在是点击按钮是弹出数字9,
我现在想让每一次点击都让它加1;
也就是说第一次点击的时候是1;
也就是说第二次点击的时候是2;
与此类推...
btn.onclick = (function (v) {
return function () {
alert(v++);
};
})(1)
这意味着,如果发生闭包时的对象 A 在闭包之后又发生了更改(Javascript 总是以引用的方式传值),那么闭包内的对象 A 的值也就同时发生了改变。在循环中这种影响被真正体现出来,就像楼主给的代码的第二段中的 CreateArray2 和 第 23 楼那样
为了消出这种影响,可以使用楼主给的示例代码中的 CreateArray1 的做法所以,23 楼的朋友没有认真看楼主的贴子。
顺便说一下,关于闭包,欢迎访问我的博客上关于闭包的文章,阮一峰也写了专门介绍 Javascript 的文章
最后,注意一下,要正确地使用闭包。不正确的闭包会导致内存泄露、堆栈溢出等问题。
/**
* 为 element 使用 handler 处理程序添加至 event 事件
* 兼容 IE 及 Firefox 等浏览器
*
* 例如为 botton 对象添加 onclick 事件,使用 clickEvent
* 方法作为处理程序:
* Event.addEvent(botton, 'click', clickEvent);
*
* @param element 需要添加事件的对象(Object)
* @param event 需要添加的事件名称(String),不加“on”
* @param handler 需要添加的方法引用(Function)
*/
addEvent : function(element, event, handler) {
if(element.attachEvent) {
element.attachEvent('on' + event, handler);
} else if (element.addEventListener) {
element.addEventListener(event, handler, false);
} else {
element['on' + event] = handler;
}
},/**
* 添加事件处理程序时,只能添加一个方法的引用,并不能给
* 方法加上参数。比如定义了 clickEvent(str) 这个方法,现
* 在要将其作为 obj 的 onclick 的事件处理程序,就可以用:
* obj.onclick = Event.getFuntion(null, clickEvent, str);
*/
getFunction : function(obj, fun) {
if (!fun) {
return function(){};
}
var args = [];
obj = obj || window;
for(var i = 2; i < arguments.length; i++) {
args.push(arguments[i]);
}
return function() {
fun.apply(obj, args);
};
}
//(1)
function (n) {
alert(n);
} (3); //没有效果
//(2)
(function (n) {
alert(n);
})(3); //会弹出3
//(3)
var b = function (n) {
alert(n);
} (3); //也会弹出3
//(4)
var b1 = function (n) {
alert(n);
}
b1(3); //也会弹出3
/*从上面代码中我可以得出
1.(1)和(2)的区别在于(1)没有执行,(2)执行啦
2.()表示让匿名函数立刻执行
*/
这个我补充一下真正的原因function (n) {
alert(n);
} (3)
这个不执行是因为浏览器引擎并不支持这种格式,它不知道
function (n) {
alert(n);
}
是一个函数,所以才用()括起来,告诉浏览器,这是一个函数,并且我要执行它但其实不一定用()括起来才可以,我们只要用任意运算符,"~","+","-"等等,告诉浏览器这是一个函数,都可以实现,如
~function (n) {
alert(n);
} (3)
+function (n) {
alert(n);
} (3)
-function (n) {
alert(n);
} (3)
有的回复
function (n) {
alert(n);
}
是一个函数,所以才用()括起来,告诉浏览器,这是一个函数,并且我要执行它你这句话 有问题
此时 只是创建了一个函数 但是 并没有执行它。
如果换成这样
(function (n) {
alert(n);
})(3); //会弹出3
就是创建了一个匿名函数,并且即时执行
首先js中是没有“块状作用域”的,请看下面例子
//scope1 作用域1
for (int i = 0; i < 10; i++){
//scope2 作用域2
String str = "123";
}
Systen.out.print(i);
Systen.out.print(str);
在有块状作用域的语言中,scope1与scope2是不同的作用域,所以
Systen.out.print(i);与Systen.out.print(str);都应该报错,i,str未定义
但js并没有块状作用域,看以下例子
//scope1 作用域1
for (var i = 0; i < 10; i++){
//scope2 作用域2
var str = "123";
}
alert(i);
alert(str); 在js中scope1与scope2是同级的,所以alert(i)打印出10, alert(str)打印出123
不单for是这种情况,if,while等都是一样的, 上面例子等同于
//scope1 作用域1
var i = 0;
var str;
for (; i < 10; i++){
//scope2 作用域2
str = "123";
}
alert(i);
alert(str);
所以
//scope1 作用域1
var els = document.getElementsByTagName("li");
for (var i = 0, j = els.length; i < j; i++){
//scope2 作用域2
var el = els[i];
el.onclick = function(){
//scope3 作用域3
alert(i);
}
}
其实等同于 //scope1 作用域1
var els = document.getElementsByTagName("li");
var i = 0, j = els.length; for (; i < j; i++){
//scope2 作用域2
var el = els[i];
el.onclick = fn;
} function fn(){
//scope3 作用域3
alert(i); //当执行onclick时,i已经循环完毕
}
这时大家会想,scope3与scope1,scope2是不同一个作用域,为什么还能打印出来,
这是因为js有作用域链这种思想,当i在scope3找不到的时候,会向上级作用域scope2访问,如果类推,
直到scope2访问到,所以这里的i其实就是scope1中的i,这时i已经是循环完毕了。
因此要避免这种情况,我们就要从它的作用域入手了,请看改造例子 //scope1 作用域1
var els = document.getElementsByTagName("li");
for (var i = 0, j = els.length; i < j; i++){
//scope2 作用域2
var el = els[i];
el.onclick = function(i){
//scope3 作用域3
return function(){
//scope4 作用域4
alert(i)
}
}(i)
} 因为作用域链,alert(i)访问scope4没有,向上级scope3访问,它发现i已经由(i)传进来赋值了,
所以alert(i)这里的i其实是scope3作用域中的i,而并不是scope1中的i 而如果我们改成这样
//scope1 作用域1
var els = document.getElementsByTagName("li");
for (var i = 0, j = els.length; i < j; i++){
//scope2 作用域2
var el = els[i];
el.onclick = function(){ //这里没有声明形参
//scope3 作用域3
return function(){
//scope4 作用域4
alert(i)
}
}(i)
} alert(i)中的i访问到的就是scope1的i,打印出来的还是循环完毕后的i...
其实我意思是用()包着函数的原理是告诉引擎,这是一个函数,用其他运算符如"~", "+","-"等告诉引擎这是个函数就都可以实现并且我要执行它,这句话是指最后加上()的时候
+function(n){
alert(n)
}(1)“+”是告诉引擎
function(n){
alert(n)
}是一个函数,(1)是执行它
这样写
function (n) {
alert(n);
}(3)
是语法错误;如果换成
function foo(n) {
alert(n);
}(3)
则没有问题,实际上这相当于
function foo(n) {
alert(n);
};
(3);
alert(n);
}(3)
这种写法并不是语法错误,只是引擎解析出来的与我们想做的不同而已,这里引擎认为是没语法问题的
[在此错误处中断] function (n) {
你应该是在谷歌浏览器中测的吧?IE6与FF是没问题的,这是不同宿主引擎的标准不同
function (n) {
alert(n);
} (3); //没有效果这个在IE9和FF6中都是不能运行的,是语法错误吧.
代码如下:
但是下面的代码没有得到我想要的效果,而是点击所有的"例子"都是4.
这个原因就是闭包造成的.每个点击onclick引用的函数都是alert()
当真个循环结束的时候,alert()函数返回的值是最大值.
怎么解决这个问题了
看func2()
//怎么理解这个话www.105h.com(function (n) { return function () { alert(n) }; })(v);
立刻执行当前函数,当前例子onclick引用的函数就是function () { alert(n) },n的值就是当前v的值
*/
function func1() {
var v;
for (var i = 1; i < 5; i++) {
v = i;
alert(n);
} (3)
语法错误, 函数声明不能被执行 。
(function (n) {
alert(n);
}) (3)
ok, 函数声明被括号运算符强制转化成表达式. 可以执行.
应该搞得专业一些,
1、看看雅虎34法则中关于js的论述。2、给你几个例子看看: http://my.oschina.net/u/150089/codelist
关于JS GC 这块 我没有研究.