不要贴链接
根据自己的理解讲解下
最好是有代码有注释
根据自己的理解讲解下
最好是有代码有注释
解决方案 »
- jQuery ui ,如何取得拖拽后的 drop对象
- jquery easyinsert初始化的问题 跪求
- 如何用JavaScript控制table动态插入行
- 路过的javascript朋友请帮我看分析下,值为什么没传过来。
- 再问个简单的问题:在javascript或vbscript中有没有控件数组?
- 怎麼在保持原table內容時在table加入一行<tr></tr>???
- 如何知道一个页面的总高度
- 如何取子串!
- help me,help me
- 【萌新求救】如何用jq实现鼠标移动到格子变色,鼠标点击变另一种颜色,再次点击变回原色
- 请您写出一段html/js代码, 实现下面的页面功能
- extjs formpanel panel.getForm.load();
为什么使用闭包?
我只知道,之前看过一些用JS做出来比较炫的网站,然后看人家的JS里有很多对象和函数。而且对象的结构比较复杂,函数间的调用非常灵活
比如:argments.callee就是函数体本身,arguments.callee.caller就是函数体的调用函数体
这是个比较经典的话题,相信LZ应该看过
我意思 你如果对这个东西 自己的理解,在项目应用个js闭包的话
可以跟我分享下,贴链接,我也会search
.take(100)
.selectMany(x=> x.GetFllowers())
.Action(y=> {y.state="参与"; return y; })
.where(y=> y.isHappy);
.Count();
当然,我这里没有特指jquery,也不是特指linq,而是指一个通用的概念。这里不但是筛选操作使用了闭包,而且就是执行一个操作也使用了闭包。由于闭包返回了被操作数据,使得你就可以继续用连缀的方式继续写程序。从而把一个程序过程用一句话就写完。你的程序更像是数据说明,而不是一堆方法。
{
.....执行一些针对obj的方法
Fun<T> delegate= ()=>{ return obj; };
return delegate;
}
这样,你其实可以使用类似这样的代码来调用var mydata= data.Process()();
等于Process返回了一个函数,调用这个函数就又返回了当初输入的那个数据。我想有些喜好“玩玄机”的人这样来讲解闭包。这可能就让你蒙了!
那我想你可能很少写过连缀代码,包括Linq。不然不会对着连缀代码说不是连缀代码。
.Where(x=> {x.field=3; return true;}
.Count();
如果你看不出这个代码可以执行,我就没有办法了。你需要先去学学任何一种连缀写程序的风格。这里,Where这个方法必须返回bool,所以那里就写return true(其实写return false也是一样)。我把方法写在Where里边,因为Where是支持闭包的。这里的目的就是在一个连缀写法写成的Linq代码中去调用一个自定义方法(而传统的给一个属性赋值的写法,都是不支持闭包的)。
这里 为什么 要写return true;如果写return false 有什么不同?可以不写嘛?
闭包主要是用在操作集合上,你可以用一条极富表现力的、函数说明性语句来写程序,而不是一堆一堆循环操作语句排列在一起。这个仔细看看所有的应用的例子就行了。核心就是为极大地简化那些集合操作程序的代码量,让程序变得更加适合“有读数学函数符号的习惯的人”去读。
比如下面这段代码
static void Main(string[] args)
{
Action<string> a = Test();
Action<string> b = Test();
a("a");
a("a");
b("b");
a("a");
b("b");
b("b");
Console.ReadKey();
} private static Action<string> Test()
{
int i = 0;
return delegate(string str) { i++; Console.WriteLine(str + i); };
}对于Test方法内的变量i,按道理在Test方法返回后就已经不存在了,但是实际上仍然存在于返回的delegate的闭包里。并且对于每个返回的delegate,闭包都是独立的。
{
int i = 0;
A a=new A();
a.i = i;
return a.method;
}
class A
{
public int i; public void method(string str)
{
i++;
Console.WriteLine(str + i);
}
} 这并不是什么“对于Test方法内的变量i,按道理在Test方法返回后就已经不存在了”。这并不是什么i诡异地移植到方法里,而是赋值给返回时所带着的新对象的字段(或者属性)了。i当然已经不存在了,但是i的值依然存在。
{
object i = 0;
A a=new A();
a.j = i;
return a.method;
}
class A
{
public object j; public void method(string str)
{
j= (int)j+1;
Console.WriteLine(str + (int)j);
}
} 这个时候可能你就不说“i的作用域跑到Test之外了吧?!你会清楚地知道其实j和i引用了同一个对象,i已经没用了,但是i的引用值仍然在j中。
if(n>0) return n+fn(n-1);
return 0;
}
alert(fn(10))var s=(function(n){
if(n>0) return n+arguments.callee(n-1);
return 0;
})(10);
alert(s)
很像C#里的外部声明的一个匿名委托,但是C#里不能像JS那样直接使用,还是很借助一下委托
当然Linq的Aggregate方法完全可以实现上述算法
query.Contraint("field1",1);
query.Contraint("field2","a",GT);
var result= query.Execute();
连缀之后,就写成了var result= dbcontext.CreateAQuery()
.Where(q=> q.Contraint("field1",1))
.And(q=> q.Contraint("field2","a",GT));
.Execute();
为什么?因为我们将原来的Contraint方法从一个方法重新设计变成了一个Func<>。Contraint方法它输入的是一个Query,以及一些其它参数,当它对Query进行了修改,结果继续抛出这个修改之后的Query,供其继续进行连缀操作。我们都知道Func<>是可以被c#编译器使用lamda表达式方式来创建的,在Linq中处处可见。同样的那个Linq例子,为了连缀,我把 x.field=3 这个原本不考虑Func<>模式的语句,封装到Where的Func<>表达式中,好让集合操作的繁琐代码可以在一行中就写完。这就利用了闭包。
function x()
{
----
}
x()这样就会生成一个作用域,在函数的这个作用域里就可以保存东西当把函数作为事件句柄的时候
如
<input type="button" id="b" value="b" />
<script type="text/javascript">var i = 0;
document.getElementById("b").onclick = function()
{
alert(i)
}
i = i + 1
</script>
你可能想要点击按扭的时候,弹出一个0,但他弹出的却是1所以,你可以这样写
<input type="button" id="b" value="b" />
<script type="text/javascript">var i = 0;
document.getElementById("b").onclick = function()
{
var j = i;//变量保存起来
return function()
{
alert(j)
}
}()//执行这个函数
i = i + 1
</script>
document.getElementById("b").onclick = function(i)
{
return function()
{
alert(i)
}
}(i)
i = i + 1
</script>
最后那个 js写错了,是这样
当然有,你定义返回类型为Delegate(委托类型的抽象父类)就是了
常见的Linq中Lambda实质就是返回Action<T> Func<T>之类的匿名委托
2.在应用程序中谨慎使用闭包技术,隐晦难懂,不符合"最小知识依赖"原则;
3.我写了一个例子,说明如何实现一个js闭包:
http://topic.csdn.net/u/20110803/06/d9c07e8b-e0f5-4632-a70f-770376a755d7.html?seed=1976238147&r=74738345#r_74738345
另外sp的解释有些问题,并没有“赋值给返回时所带着的新对象的字段”这个过程,i就存在于返回的新对象中。
测试下下面代码private static Action<string> Test()
{
int i = 0;
Action<string> action = delegate(string str) { i++; Console.WriteLine(str + i); };
i = 100;
return action;
}
害我又爬回29#看了一下,以为发现了P哥的惊世Bug(名人不好当啊..)
结果还是大叹一声,其实是你理解错了下面的P哥的代码
private static Action<string> Test()
{
int i = 0;
A a=new A();
a.i = i; //这里本就是属性或字段的赋值过程
//之后就算对i作任何操作,都不会影响到类a的成员,int换成object引用型也是一样
return a.method;
}“Test()返回之后,i将一直存在”,LS说的也没有错,因为LS最终要返回的action直接访问了外部变量i,对t的任何调用,都会存在一个对i的引用(所以i不至于被回收销毁),但是和P哥说的赋值也并没有矛盾之处
var t = Test();
t("t");
“i当然已经不存在了,但是i的值依然存在”
对于P哥的代码来说也没有任何问题,P哥返回的目标对象是a.method,而i对于它来说没有任何关系(引用),它唯一访问的只是类A自身的成员。只要Test()一返回,i自然是没有用了(因为已经出了Test方法,之后的对t(str)的调用,因为返回的是实例方法a.method的,所以对那个new出来的实例a的引用将一直存在(A只会在返回Test()时实例化一次),直到t失效。所以上一次执行t(str)之后,会直接影响到下一次的输出(因为a.i++了)
对于P哥的代码来说也没有任何问题,P哥返回的目标对象是a.method,而i对于它来说没有任何关系(引用),它唯一访问的只是类A自身的成员。只要Test()一返回,i自然是没有用了(因为已经出了Test方法,之后的对t(str)的调用,实质都是对a.method的引用,而这个方法又需要实例a的引用,所以对new出来的a的引用将一直存在(A只会在Test()返回时实例化一次),直到t失效。
所以对于P哥的代码,上一次执行t(str)之后,会直接影响到下一次的输出(因为a.i++了)
你没明白我的意思
我的意思是并不存在i和A.i这2个变量,没有赋值这个过程,i和A.i是一个东西。
所以也不存在“i已经不存在,但i的值仍然存在”这样的说法了。
编译器确实玩了一些障眼法,但是闭包本就是一个概念上的东西,用具体实现来解释并不恰当。就好比用虚表、指针来解释类的含义不合适一样。
没错,对于你从delegate内部访问i并返回这个action的做法来说,i的确是一个东西,因为action对i的引用将一直存在。
但是对于P哥的做法还是这样吗?请看代码(PS:这里并没有针对你的意思,只是共同讨论一下,因为我也有很多不明白的地方)static void Main(string[] args)
{
var t = Test();
for (int i = 1; i < 10; i++)
{
t(i.ToString());
}
} private static Action<string> Test()
{
int i = 0;
A a = new A();
a.i = i;
i = 1000000;
//这里将 i 的值改变,并输出。
//不管之后对t调用多少次,都不影响这里的输出,且仅当在Test()返回给t时输出一次
Console.WriteLine("Member i in Test() is {0}", i);
return a.method;
} class A
{
public int i; public void method(string callNum)
{
i++;
Console.WriteLine("Test delegate instance was called {0} times, currently A.i is {1}", callNum, i);
}
}
/*
Member i in Test() is 1000000
Test delegate instance was called 1 times, currently A.i is 1
Test delegate instance was called 2 times, currently A.i is 2
Test delegate instance was called 3 times, currently A.i is 3
Test delegate instance was called 4 times, currently A.i is 4
Test delegate instance was called 5 times, currently A.i is 5
Test delegate instance was called 6 times, currently A.i is 6
Test delegate instance was called 7 times, currently A.i is 7
Test delegate instance was called 8 times, currently A.i is 8
Test delegate instance was called 9 times, currently A.i is 9
请按任意键继续. . .
*/
“官方”的解释是:所谓“闭包”,指的是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。 相信很少有人能直接看懂这句话,因为他描述的太学术。我想用如何在Javascript中创建一个闭包来告诉你什么是闭包,因为跳过闭包的创建过程直接理解闭包的定义是非常困难的。
看下面这段代码: function a(){
var i=0;
function b(){ alert(++i); }
return b;
} var c = a();
c(); 这段代码有两个特点: 1、函数b嵌套在函数a内部;
2、函数a返回函数b。 这样在执行完var c=a()后,变量c实际上是指向了函数b,再执行c()后就会弹出一个窗口显示i的值(第一次为1)。这段代码其实就创建了一个闭包,为什么?因为函数a外的变量c引用了函数a内的函数b,就是说: 当函数a的内部函数b被函数a外的一个变量引用的时候,就创建了一个闭包。 我猜想你一定还是不理解闭包,因为你不知道闭包有什么作用,下面让我们继续探索。二、闭包有什么作用?
简而言之,闭包的作用就是在a执行完并返回后,闭包使得Javascript的垃圾回收机制GC不会收回a所占用的资源,因为a的内部函数b的执行需要依赖a中的变量。这是对闭包作用的非常直白的描述,不专业也不严谨,但大概意思就是这样,理解闭包需要循序渐进的过程。 在上面的例子中,由于闭包的存在使得函数a返回后,a中的i始终存在,这样每次执行c(),i都是自加1后alert出i的值。 那 么我们来想象另一种情况,如果a返回的不是函数b,情况就完全不同了。因为a执行完后,b没有被返回给a的外界,只是被a所引用,而此时a也只会被b引 用,因此函数a和b互相引用但又不被外界打扰(被外界引用),函数a和b就会被GC回收。(关于Javascript的垃圾回收机制将在后面详细介绍)三、闭包内的微观世界
如 果要更加深入的了解闭包以及函数a和嵌套函数b的关系,
我们需要引入另外几个概念:函数的执行环境(excution context)、活动对象(call object)、作用域(scope)、作用域链(scope chain)。以函数a从定义到执行的过程为例阐述这几个概念。 1、当定义函数a的时候,js解释器会将函数a的作用域链(scope chain)设置为定义a时a所在的“环境”,如果a是一个全局函数,则scope chain中只有window对象。 2、当函数a执行的时候,a会进入相应的执行环境(excution context)。 3、在创建执行环境的过程中,首先会为a添加一个scope属性,即a的作用域,其值就为第1步中的scope chain。即a.scope=a的作用域链。 4、然后执行环境会创建一个活动对象(call object)。活动对象也是一个拥有属性的对象,但它不具有原型而且不能通过JavaScript代码直接访问。创建完活动对象后,把活动对象添加到a的作用域链的最顶端。此时a的作用域链包含了两个对象:a的活动对象和window对象。 5、下一步是在活动对象上添加一个arguments属性,它保存着调用函数a时所传递的参数。 6、最后把所有函数a的形参和内部的函数b的引用也添加到a的活动对象上。在这一步中,完成了函数b的的定义,因此如同第3步,函数b的作用域链被设置为b所被定义的环境,即a的作用域。 到此,整个函数a从定义到执行的步骤就完成了。此时a返回函数b的引用给c,又函数b的作用域链包含了对函数a的活动对象的引用,也就是说b可以访问到a中定义的所有变量和函数。函数b被c引用,函数b又依赖函数a,因此函数a在返回后不会被GC回收。 当函数b执行的时候亦会像以上步骤一样。因此,执行时b的作用域链包含了3个对象:b的活动对象、a的活动对象和window对象,如下图所示: 如图所示,当在函数b中访问一个变量的时候,搜索顺序是先搜索自身的活动对象,如果存在则返回,如果不存在将继续搜索函数a的活动对象,依 次查找,直到找到为止。如果整个作用域链上都无法找到,则返回undefined。如果函数b存在prototype原型对象,则在查找完自身的活动对象 后先查找自身的原型对象,再继续查找。这就是Javascript中的变量查找机制。
四、闭包的应用场景
1、保护函数内的变量安全。以最开始的例子为例,函数a中i只有函数b才能访问,而无法通过其他途径访问到,因此保护了i的安全性。 2、在内存中维持一个变量。依然如前例,由于闭包,函数a中i的一直存在于内存中,因此每次执行c(),都会给i自加1。 以上两点是闭包最基本的应用场景,很多经典案例都源于此。 五、Javascript的垃圾回收机制 在Javascript中,如果一个对象不再被引用,那么这个对象就会被GC回收。如果两个对象互相引用,而不再被第3者所引用,那么这两个互相引用的对象也会被回收。因为函数a被b引用,b又被a外的c引用,这就是为什么函数a执行后不会被回收的原因。
今早晨看到的,不过我没接触过,所以还是不懂,LZ去看看吧
在计算机科学中,闭包(Closure)是词法闭包(Lexical Closure)的简称,是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。所以,有另一种说法认为闭包是由函数和与其相关的引用环境组合而成的实体。
http://blog.csdn.net/sandy945/article/details/5929577一个javascript小例子
http://topic.csdn.net/u/20100702/08/b0d6c989-eba2-42e3-98b3-63120841c31b.html你先看下里面的代码,看能得出什么结论。它们从两个角度说明了闭包的一些特性, 计数器说明的是js中闭包的特性。另一个适用于其他语言的闭包下午我再文字回复下。
http://www.cn-cuckoo.com/2007/08/01/understand-javascript-closures-72.html
http://en.wikipedia.org/wiki/Closure_%28computer_science%29
js的闭包。我只是在循环绑定中调用一个统一个公共函数的使用用过。感觉闭包的作用就是把变量的过程给保存起来了。
其他的应用还没用过。
不才译文见下,见笑了。
Peter Mortensen问:
就像老Albert所说的,“如果你不能向一个六岁的孩子解释清楚,那么其实你自己根本就没弄懂。”好吧,我试着向一个27岁的朋友就是JS闭包(JavaScript closure)却彻底失败了。
你们会怎么把它解释给一个充满好奇心的六岁孩子听呢?
注:我看过StackOverflow上给出的示例,但根本没用。
Ali的回答:
当function里嵌套function时,内部的function可以访问外部function里的变量。
function foo(x) {
var tmp = 3;
function bar(y) {
alert(x + y + (++tmp));
}
bar(10);
}
foo(2)
不管执行多少次,都会alert 16,因为bar能访问foo的参数x,也能访问foo的变量tmp。
但,这还不是闭包。当你return的是内部function时,就是一个闭包。内部function会close-over外部function的变量直到内部function结束。
function foo(x) {
var tmp = 3;
return function (y) {
alert(x + y + (++tmp));
}
}
var bar = foo(2); // bar 现在是一个闭包
bar(10);
上面的脚本最终也会alert 16,因为虽然bar不直接处于foo的内部作用域,但bar还是能访问x和tmp。
但是,由于tmp仍存在与bar闭包的内部,所以它还是会自加1,而且你每次调用bar时它都会自加1.
(考虑到六岁这个限制:我们其实可以建立不止一个闭包方法,比如return它们的数组,也可以把它们设置为全局变量。它们全都指向相同的x和相同的tmp,而不是各自有一份副本。)
注:现在来整点儿七岁的内容。
上面的x是一个字面值(值传递),和JS里其他的字面值一样,当调用foo时,实参x的值被复制了一份,复制的那一份作为了foo的参数x。
那么问题来了,JS里处理object时是用到引用传递的,那么,你调用foo时传递一个object,foo函数return的闭包也会引用最初那个object!
function foo(x) {
var tmp = 3;
return function (y) {
alert(x + y + tmp);
x.memb = x.memb ? x.memb + 1 : 1;
alert(x.memb);
}
}
var age = new Number(2);
var bar = foo(age); // bar 现在是一个引用了age的闭包
bar(10);
不出我们意料,每次运行bar(10),x.memb都会自加1。但需要注意的是x每次都指向同一个object变量——age,运行两次bar(10)后,age.memb会变成2.
这和HTML对象的内存泄漏有关,呃,不过貌似超出了答题的范围。
JohnMerlino 对Ali说:
这里有一个不用return关键字的闭包例子:
function closureExample(obj, text, timedelay) {
setTimeout(function() {
document.getElementById(objID).innerHTML = text;
}, timedelay);
}
closureExample(‘myDiv’, ‘Closure is created’, 500);
深夜1:37 John Pick这样回答:
JS里的function能访问它们的:
1. 参数
2. 局部变量或函数
3. 外部变量(环境变量?),包括
3.1 全局变量,包括DOM
3.2 外部函数的变量或函数。
如果一个函数访问了它的外部变量,那么它就是一个闭包。
注意,外部函数不是必需的。通过访问外部变量,一个闭包可以维持(keep alive)这些变量。在内部函数和外部函数的例子中,外部函数可以创建局部变量,并且最终退出;但是,如果任何一个或多个内部函数在它退出后却没有退出,那么内部函数就维持了外部函数的局部数据。
一个典型的例子就是全局变量的使用。
mykhal这样回答:
Wikipedia对闭包的定义是这样的:
In computer science, a closure is a function together with a referencing environment for the nonlocal names (free variables) of that function.
从技术上来讲,在JS中,每个function都是闭包,因为它总是能访问在它外部定义的数据。
Since scope-defining construction in Javascript is a function, not a code block like in many other languages, what we usually mean by closure in Javascript is a fuction working with nonlocal variables defined in already executed surrounding function.
闭包经常用于创建含有隐藏数据的函数(但并不总是这样)。
var db = (function() {
// 创建一个隐藏的object, 这个object持有一些数据
// 从外部是不能访问这个object的
var data = {};
// 创建一个函数, 这个函数提供一些访问data的数据的方法
return function(key, val) {
if (val === undefined) { return data[key] } // get
else { return data[key] = val } // set
}
// 我们可以调用这个匿名方法
// 返回这个内部函数,它是一个闭包
})();
db('x'); // 返回 undefined
db('x', 1); // 设置data['x']为1
db('x'); // 返回 1
// 我们不可能访问data这个object本身
// 但是我们可以设置它的成员
看了这么多外国大牛的解答,不知道你懂还是不懂,反正我是懂了。
P.S. 发布文章之后看到@xiaotie的一篇文章,觉得有必要推荐一下,因为其剖析得更为深入。有人说应该在文章结尾对闭包进行总结,可惜小弟才疏学浅,不能给出一个精辟的总结。
@xiaotie对闭包的总结如下:
(1)闭包是一种设计原则,它通过分析上下文,来简化用户的调用,让用户在不知晓的情况下,达到他的目的;
(2)网上主流的对闭包剖析的文章实际上是和闭包原则反向而驰的,如果需要知道闭包细节才能用好的话,这个闭包是设计失败的;
(3)尽量少学习。
大家学习学习。转自博客园
不才译文见下,见笑了。
Peter Mortensen问:
就像老Albert所说的,“如果你不能向一个六岁的孩子解释清楚,那么其实你自己根本就没弄懂。”好吧,我试着向一个27岁的朋友就是JS闭包(JavaScript closure)却彻底失败了。
你们会怎么把它解释给一个充满好奇心的六岁孩子听呢?
注:我看过StackOverflow上给出的示例,但根本没用。
Ali的回答:
当function里嵌套function时,内部的function可以访问外部function里的变量。
function foo(x) {
var tmp = 3;
function bar(y) {
alert(x + y + (++tmp));
}
bar(10);
}
foo(2)
不管执行多少次,都会alert 16,因为bar能访问foo的参数x,也能访问foo的变量tmp。
但,这还不是闭包。当你return的是内部function时,就是一个闭包。内部function会close-over外部function的变量直到内部function结束。
function foo(x) {
var tmp = 3;
return function (y) {
alert(x + y + (++tmp));
}
}
var bar = foo(2); // bar 现在是一个闭包
bar(10);
上面的脚本最终也会alert 16,因为虽然bar不直接处于foo的内部作用域,但bar还是能访问x和tmp。
但是,由于tmp仍存在与bar闭包的内部,所以它还是会自加1,而且你每次调用bar时它都会自加1.
(考虑到六岁这个限制:我们其实可以建立不止一个闭包方法,比如return它们的数组,也可以把它们设置为全局变量。它们全都指向相同的x和相同的tmp,而不是各自有一份副本。)
注:现在来整点儿七岁的内容。
上面的x是一个字面值(值传递),和JS里其他的字面值一样,当调用foo时,实参x的值被复制了一份,复制的那一份作为了foo的参数x。
那么问题来了,JS里处理object时是用到引用传递的,那么,你调用foo时传递一个object,foo函数return的闭包也会引用最初那个object!
function foo(x) {
var tmp = 3;
return function (y) {
alert(x + y + tmp);
x.memb = x.memb ? x.memb + 1 : 1;
alert(x.memb);
}
}
var age = new Number(2);
var bar = foo(age); // bar 现在是一个引用了age的闭包
bar(10);
不出我们意料,每次运行bar(10),x.memb都会自加1。但需要注意的是x每次都指向同一个object变量——age,运行两次bar(10)后,age.memb会变成2.
这和HTML对象的内存泄漏有关,呃,不过貌似超出了答题的范围。
JohnMerlino 对Ali说:
这里有一个不用return关键字的闭包例子:
function closureExample(obj, text, timedelay) {
setTimeout(function() {
document.getElementById(objID).innerHTML = text;
}, timedelay);
}
closureExample(‘myDiv’, ‘Closure is created’, 500);
深夜1:37 John Pick这样回答:
JS里的function能访问它们的:
1. 参数
2. 局部变量或函数
3. 外部变量(环境变量?),包括
3.1 全局变量,包括DOM
3.2 外部函数的变量或函数。
如果一个函数访问了它的外部变量,那么它就是一个闭包。
注意,外部函数不是必需的。通过访问外部变量,一个闭包可以维持(keep alive)这些变量。在内部函数和外部函数的例子中,外部函数可以创建局部变量,并且最终退出;但是,如果任何一个或多个内部函数在它退出后却没有退出,那么内部函数就维持了外部函数的局部数据。
一个典型的例子就是全局变量的使用。
mykhal这样回答:
Wikipedia对闭包的定义是这样的:
In computer science, a closure is a function together with a referencing environment for the nonlocal names (free variables) of that function.
从技术上来讲,在JS中,每个function都是闭包,因为它总是能访问在它外部定义的数据。
Since scope-defining construction in Javascript is a function, not a code block like in many other languages, what we usually mean by closure in Javascript is a fuction working with nonlocal variables defined in already executed surrounding function.
闭包经常用于创建含有隐藏数据的函数(但并不总是这样)。
var db = (function() {
// 创建一个隐藏的object, 这个object持有一些数据
// 从外部是不能访问这个object的
var data = {};
// 创建一个函数, 这个函数提供一些访问data的数据的方法
return function(key, val) {
if (val === undefined) { return data[key] } // get
else { return data[key] = val } // set
}
// 我们可以调用这个匿名方法
// 返回这个内部函数,它是一个闭包
})();
db('x'); // 返回 undefined
db('x', 1); // 设置data['x']为1
db('x'); // 返回 1
// 我们不可能访问data这个object本身
// 但是我们可以设置它的成员
看了这么多外国大牛的解答,不知道你懂还是不懂,反正我是懂了。
P.S. 发布文章之后看到@xiaotie的一篇文章,觉得有必要推荐一下,因为其剖析得更为深入。有人说应该在文章结尾对闭包进行总结,可惜小弟才疏学浅,不能给出一个精辟的总结。
@xiaotie对闭包的总结如下:
(1)闭包是一种设计原则,它通过分析上下文,来简化用户的调用,让用户在不知晓的情况下,达到他的目的;
(2)网上主流的对闭包剖析的文章实际上是和闭包原则反向而驰的,如果需要知道闭包细节才能用好的话,这个闭包是设计失败的;
(3)尽量少学习。
大家学习学习。
这里说的是针对30#的情况,不是29#。
private static Action<string> Test()
{
object i = 0;
A a=new A();
a.j = i;
return a.method;
}
class A
{
public object j; public void method(string str)
{
j= (int)j+1;
Console.WriteLine(str + (int)j);
}
}
我又回去看了看书才明白了一点点什么是值类型差点又要说值类型和函数都是压栈的方式访问的,还是围观高人来分解
但是你这个确实 不是闭包
链式操作 只是指在一个操作后返回一个对象(接口) 这个对象你可以继续写调用方法 使你可以方便的撰写程序
这个和js里面的闭包完全不是一个概念吧面向对象里面 inerclass 才是类似js闭包的机制闭包说到底就是一种封装 吧不想让外界直接访问的东西 通过闭包的方式 封装起来 使得外部只能通过 指定的接口来访问
但是 实际 使用中 我们往往 是为了 实现个性化操作
相同的接口 但是操作的是不同的 数据内容 不明白js闭包的人 只是还没 领悟应用的变化
var myop=(function(val){
return function(){alert(val);}
})(100);
myop()//
上面这段代码就是实现闭包的最简单形式
val被初始化为100 被封装在匿名函数里面了 这个函数返回一个function 只有这个function可以操作val
就是这么简单的东西 关键就看你怎么用了我觉得 大部分人 化在问基础问题上的时间太多了 这样的问题 自己多动手写写代码 就能体悟了闭包属于 机制问题 机制是不变的东西 不管你怎么玩 他都是一样的表现方式没明白闭包的人 建议 吧js的基础语法知识好好的看看 平时多动手 少动嘴下面不说了 明白就是明白 不明白就是不明白