闭包是什么,有什么特性,对页面有什么影响
闭包是可以包含自由(未绑定到特定对象)变量的代码块;这些变量不是在这个代码块内或者任何全局上下文中定义的,而是在定义代码块的环境中定义(局部变量)。“闭包” 一词来源于以下两者的结合:要执行的代码块(由于自由变量被包含在代码块中,这些自由变量以及它们引用的对象没有被释放)和为自由变量提供绑定的计算环境(作用域)。在 Scala、Scheme、Common Lisp、Smalltalk、Groovy、JavaScript、Ruby、 Python、Go、Lua、objective c、swift 以及Java(Java8及以上)等语言中都能找到对闭包不同程度的支持。 闭包 (closure)是个精确但又很难解释的电脑名词。在 Perl 里面,闭包是以 匿名函数的形式来实现,具有持续参照位于该函数范围之外的文字式变数值的能力。这些外部的文字变数会神奇地保留它们在闭包函数最初定义时的值 (深连结)。如果一个程式语言容许函数递回另一个函数的话 (像 Perl 就是),闭包便具有意义。要注意的是,有些语言虽提供匿名函数的功能,但却无法正确处理闭包; Python 这个语言便是一例。如果要想多了解闭包的话,建议你去找本功能性程式 设计的教科书来看。Scheme这个语言不仅支持闭包,更鼓励多加使用。以下是个典型的产生函数的函数:sub add_function_generator {return sub { shift + shift };}$add_sub = add_function_generator();$sum = &$add_sub(4,5); # $sum是 9了闭包用起来就像是个函数样板,其中保留了一些可以在稍後再填入的空格。add_function_generator() 所递回的匿名函数在技术上来讲并不能算是一个闭包, 因为它没有用到任何位在这个函数范围之外的文字变数。把上面这个例子和下面这个make_adder()函数对照一下,下面这个函数所递回的匿名函数中使用了一个外部的文字变数。这种指明外部函数的作法需要由 Perl递回一个适当的闭包,因此那个文字变数在匿名函数产生之时的值便永久地被锁进闭包里。sub make_adder {my $addpiece = shift;return sub { shift + $addpiece };}$f1 = make_adder(20);$f2 = make_adder(555);这样一来&$f1($n) 永远会是 20加上你传进去的值$n ,而&$f2($n) 将 永远会是 555加上你传进去的值$n。$addpiece的值会在闭包中保留下来。闭包在比较实际的场合中也常用得到,譬如当你想把一些程式码传入一个函数时:my $line;timeout(30,sub { $line = });如果要执行的程式码当初是以字串的形式传入的话,即'$line = ' ,那么timeout() 这个假想的函数在回到该函数被呼叫时所在的范围後便无法再撷取$line这个文字变数的值了。语法结构编辑Groovy的闭包闭包(Closure)是Java所不具备的语法结构。闭包就是一个代码块,用“{ }”包起来。此时,程序代码也就成了数据,可以被一个变量所引用(与C语言的函数指针比较类似)。闭包的最典型的应用是实现回调函数(callback)。Groovy的API大量使用闭包,以实现对外开放。闭包的创建过程很简单,例如:{ 参数 ->代码...}参考下面的例子代码,定义了c1和c2两个闭包,并对它们进行调用:def c1 = { println it }def c2 = { text -> println text }c1.call("content1") //用call方法调用闭包c2("content2") //直接调用闭包“->;”之前的部分为闭包的参数,如果有多个参数,之间可用逗号分割;“->;”之后的部分为闭包内的程序代码。如果省略了“->;”和它之前的部分,此时闭包中代码,可以用名为“it”的变量访问参数。闭包的返回值和函数的返回值定义方式是一样的:如果有return语句,则返回值是return语句后面的内容;如果没有return语句,则闭包内的最后一行代码就是它的返回值。[1]环境表达编辑在Javascript中闭包(Closure)什么是闭包“官方”的解释是:所谓“闭包”,指的是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。相信很少有人能直接看懂这句话,因为他描述的太学术。我想用如何在Javascript中创建一个闭包来告诉你什么是闭包,因为跳过闭包的创建过程直接理解闭包的定义是非常困难的。看下面这段代码123456789function 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的垃圾回收机制将在后面详细介绍)另一个例子模拟私有变量function Counter(start){var count = start;return{increment:function(){count++;},get:function(){return count;}}}var foo =Counter(4);foo.increment();foo.get();// 5结果这里,Counter 函数返回两个闭包,函数 increment 和函数 get。 这两个函数都维持着 对外部作用域 Counter 的引用,因此总可以访问此作用域内定义的变量 count.文法objective c的闭包(block)objective c 中的的闭包,是通过block实现的。Apple在C,Objective-C和C++中扩充了Block这种文法的,并且在GCC4.2中进行了支持。你可以把它理解为函数指针,匿名函数,闭包,lambda表达式,这里暂且用块对象来表述,因为它们之间还是有些许不同的。声明一个块如果以内联方式使用块对象,则无需声明。块对象声明语法与函数指针声明语法相似,但是块对象应使用脱字符(^)而非星号指针 (*)。下面的代码声明一个aBlock变量,它标识一个需传入三个参数并具有float返回值的块。float (^aBlock)(const int*, int, float);l 创建一个块块使用脱字符(^)作为起始标志,使用分号作为结束标志。下面的例子声明一个简单块,并且将其赋给之前声明的block变量(oneFrom)。int (^oneFrom)(int);oneFrom = ^(int anInt) {return anInt - 1;};微观世界如 果要更加深入的了解闭包以及函数a和嵌套函数b的关系,我们需要引入另外几个概念:函数的执行环境(execution context)、活动对象(call object)、作用域(scope)、作用域链(scope chain)。以函数a从定义到执行的过程为例阐述这几个概念。1、当定义函数a的时候,js解释器会将函数a的作用域链(scope chain)设置为定义a时a所在的“环境”,如果a是一个全局函数,则scope chain中只有window对象。2、当函数a执行的时候,a会进入相应的执行环境(execution 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中,如果一个对象不再被引用,那么这个对象就会被GC回收。如果两个对象互相引用,而不再被第3者所引用,那么这两个互相引用的对象也会被回收。因为函数a被b引用,b又被a外的c引用,这就是为什么函数a执行后不会被回收的原因。匿名内部在Python中的闭包(Closure)学过Java GUI编程的人都知道定义匿名内部类是注册监听等处理的简洁有效手段,闭包的定义方式有点类似于这种匿名内部类,但是闭包的作用威力远远超过匿名内部类,这也是很多流行动态语言选择闭包的原因,相信你在JavaScript中已经了解它的神奇功效了。定义如果在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包(closure)。简单闭包的例子:下面是一个使用闭包简单的例子,模拟一个计数器,通过将整型包裹为一个列表的单一元素来模拟使看起来更易变:函数counter()所作的唯一一件事就是接受一个初始化的值来计数,并将该值赋给列表count成员,然后定义一个内部函数incr()。通过内部函数使用变量count,就创建了一个闭包。最魔法的地方是counter()函数返回一个incr(),一个可以调用的函数对象。运行:>>> c = counter⑸>>> type(c)>>> print c()6>>> print c()7代码格式较重要>>> c2 = counter(99)100>>> print c() 8

关于闭包的理解问题,小白求大牛解答!!
首先应该深入的理解一下闭包的概念,维基百科上关于闭包的解释理解起来比较容易些,我把前面两段话简单的处理一下:在程序语言中,闭包(Closure),又称词法闭包(Lexical Closure)或函数闭包(function closures),是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。闭包是由函数和与其相关的引用环境组合而成的实体。在一些语言中,在函数中可以(嵌套)定义另一个函数时,如果内部的函数引用了外部的函数的变量,则可能产生闭包。运行时,一旦外部的函数被执行,一个闭包就形成了,闭包中包含了内部函数的代码,以及所需外部函数中的变量的引用。理解了闭包之后,再来看你的第一个问题,虽然A处的inc函数只是声明,但是闭包在外层函数a执行的时候就已经生成,形成的闭包包括了内部函数的代码和所需外部变量的引用。根据定义,还有一点需要注意,即形成的闭包保存的是外部变量的引用,看下面的例子: var arr = []; for (var i=0; i<3; i++) { arr[i] = return function() { alert(i) } } arr[0](); arr[1](); arr[2]();每次都是弹出3,即闭包只记住外部变量存放在了哪里,在内部函数还没有执行前,它是不管你的值是什么的,任你怎么变,我执行的时候只获取最后的值。要想实现想要的效果,可以这样做: var arr = []; for (var i=0; i<3; i++) { arr[i] = function(j) { return function() { alert(j) } }(i) } arr[0](); arr[1](); arr[2]();这里用一个立即执行函数,使得每次循环的i值都记录下来了。你的第二个问题看了好几遍还是不太理解你想问什么,简单的说一些常识吧。function a(...)和var a=function(...)是函数的两种声明方式,无论哪一种,只要你没有重新给a赋值,即a还指向这个函数,那么这个函数所占据的内存就不会被回收,函数执行完毕后回收的只是函数内部声明的局部变量(如果变量没有被内部函数引用形成闭包),故而函数的局部变量在函数每次执行时都重新定义,重新赋值。
return inc;这一句是将整个函数给return出去,var c = a();这里将函数a的返回值接收,实际上c就是函数inc了,你打印一下c,看看c是什么,var c = a();console.log(c);调用c,其实就是在调用inc这个函数。你就这么理解吧,只要知道c = inc()就行了。这样说你能明白吗?

js中闭包是什么意思,有什么作用,最好举例说明啊。
函数对象可以通过作用域链相互关联起来,函数体内部的变量都可以保存在函数作用域内,这种特性在计算机科学文献中称之为“闭包”。 从技术角度讲,所有的JavaScript函数都是闭包: 它们都是对象,它们都关联到作用域链。实现计数器介绍利用闭包实现计数器,请看以下代码:var counter = (function() {var count = 0;return function() {return count ++;}})(); 以上代码定义了一个立即执行的函数,count遍历只能在这个匿名函数中可以使用。
最简单地说:内调外概括:闭包就是函数内调用外面的变量例一:[1]请看以下代码function add(a,b){return a+b;}add(5,8);结果:13接下来,请分析这段代码,和第一段代码有什么不同:function makeadd(a)return function(b){return a+b;}}var add=makeadd(5);add(8);结果:13在加粗的代码中,a并不存在于该函数作用域,而是调用了外面的a。这里的a就是闭包(closure)例二:[2]一个计数器的困境假设您想使用变量来计数,并且您希望此计数器可用于所有函数。您可以使用全局变量和函数来递增计数器:// 初始化计数器var counter = 0;// 递增计数器的函数function add() {counter += 1;}// 调用三次 add()add();add();add();// 此时计数器应该是 3上述解决方案有一个问题:页面上的任何代码都可以更改计数器,而无需调用 add()。对于 add() 函数,计数器应该是局部的,以防止其他代码更改它:// 初始化计数器var counter = 0;// 递增计数器的函数function add() {var counter = 0;counter += 1;}// 调用三次 add()add();add();add();//此时计数器应该是 3。但它是 0。它没有用,因为我们显示全局计数器而不是本地计数器。通过让函数返回它,我们可以删除全局计数器并访问本地计数器:// 递增计数器的函数function add() {var counter = 0;counter += 1;return counter;}// 调用三次 add()add();add();add();//此时计数器应该是 3。但它是 1。它没有用,因为我们每次调用函数时都会重置本地计数器。JavaScript 内部函数可以解决这个问题。JavaScript 嵌套函数所有函数都有权访问全局作用域。事实上,在 JavaScript 中,所有函数都有权访问它们“上面”的作用域。JavaScript 支持嵌套函数。嵌套函数可以访问其上的作用域。在本例中,内部函数 plus() 可以访问父函数中的 counter 计数器变量:function add() {var counter = 0;function plus() {counter += 1;}plus();return counter;}这样即可解决计数器困境,如果我们能够从外面访问 plus() 函数。我们还需要找到只执行一次 counter = 0 的方法。我们需要闭包(closure)。JavaScript 闭包var add = (function () {var counter = 0;return function () {return counter += 1;}})();add();add();add();// 计数器目前是 3例子解释变量 add 的赋值是自调用函数的返回值。这个自调用函数只运行一次。它设置计数器为零(0),并返回函数表达式。这样 add 成为了函数。最“精彩的”部分是它能够访问父作用域中的计数器。这被称为 JavaScript 闭包。它使函数拥有“私有”变量成为可能。计数器被这个匿名函数的作用域保护,并且只能使用 add 函数来修改。总结:闭包指的是有权访问父作用域的函数,即使在父函数关闭之后。参考资料:[1]MDN--JavaScript闭包[2]W3School JavaScript 闭包

js中 作用域链 和 闭包 怎么理解
scope就是作用域的英文,作用域链就的作用如下:当解释器运行到该函数处时,当前上下文环境,即当前活动对象,调用该函数,调用的同时拥有了一个配套的囊括了所有可使用的变量组成的队列(这种说法是我原创的,可能不准确),也就是所谓的作用域链属性

js关于作用域链与闭包问题?
算是半个闭包问题 你可能是这麽写的for(var i=0;ii本来就应该是21好不好 i自增到20时,判断是否小于start.length(21)true进行{}中代码之后自增21然后判断是否小于21不满足之后跳出循环所以说i=21但是21时不会进入{}中 至于你说的啥作用域链什么的我不懂

本文由 在线网速测试 整理编辑,转载请注明出处。