闭包的两个特点:
1、作为一个函数变量的一个引用 - 当函数返回时,其处于激活状态。
2、一个闭包就是当一个函数返回时,一个没有释放资源的栈区。
例1。
以下是引用片段: <script type="text/javascript"> function sayHello2(name) { var text = 'Hello ' + name; // local variable var sayAlert = function() { alert(text); } return sayAlert; } var sy = sayHello2('never-online'); sy(); </script> |
作为一个javascript程序员,应该明白上面的代码就是一个函数的引用。如果你还不明白或者不清楚的话,请先了解一些基本的知识,我这里不再叙述。
上面的代码为什么是一个闭包?
因为sayHello2函数里有一个内嵌匿名函数
sayAlert = function(){ alert(text); }
在javascript里。如果你创建了一个内嵌函数(如上例),也就是创建了一个闭包。
在C或者其它的主流语言中,当一个函数返回后,所有的局部变量将不可访问,因为它们所在的栈已经被消毁。但在javascript里,如果你声明了一个内嵌函数,局部变量将在函数返回后依然可访问。比如上例中的变量sy,就是引用内嵌函数中的匿名函数function(){ alert(text); },可以把上例改成这样:
以下是引用片段: <script type="text/javascript"> function sayHello2(name) { var text = 'Hello ' + name; // local variable var sayAlert = function() { alert(text); } return sayAlert; } var sy = sayHello2('never-online'); alert(sy.toString()); </script> |
这里也就与闭包的第二个特点相吻合。
例2。
以下是引用片段: <script type="text/javascript"> function say667() { // Local variable that ends up within closure var num = 666; var sayAlert = function() { alert(num); } num++; return sayAlert; }
var sy = say667(); sy(); alert(sy.toString()); </script> |
上面的代码中,匿名变量function() { alert(num); }中的num,并不是被拷贝,而是继续引用外函数定义的局部变量——num中的值,直到外函数say667()返回。
例3。
以下是引用片段: <script type="text/javascript"> function setupSomeGlobals() { // Local variable that ends up within closure var num = 666; // Store some references to functions as global variables gAlertNumber = function() { alert(num); } gIncreaseNumber = function() { num++; } gSetNumber = function(x) { num = x; } }
</script> <button onclick="setupSomeGlobals()">生成 - setupSomeGlobals()</button> <button onclick="gAlertNumber()">输出值 - gAlertNumber()</button> <button onclick="gIncreaseNumber()">增加 - gIncreaseNumber()</button> <button onclick="gSetNumber(5)">赋值5 - gSetNumber(5)</button> |
上例中,gAlertNumber, gIncreaseNumber, gSetNumber都是同一个闭包的引用,setupSomeGlobals(),因为他们声明都是通过同一个全局调用——setupSomeGlobals()。
你可以通过“生成”,“增加”,“赋值”,“输出值”这三个按扭来查看输出结果。如果你点击“生成”按钮,将创建一个新闭包。也就会重写gAlertNumber(), gIncreaseNumber(), gSetNumber(5)这三个函数。
如果理解以上代码后,看下面的例子:
例4。
以下是引用片段: <script type="text/javascript"> function buildList(list) { var result = []; for (var i = 0; i < list.length; i++) { var item = 'item' + list[i]; result.push( function() {alert(item + ' ' + list[i])} ); } return result; }
function testList() { var fnlist = buildList([1,2,3]); // using j only to help prevent confusion - could use i for (var j = 0; j < fnlist.length; j++) { fnlist[j](); } }
testList(); </script> 运行结果: item 3 is undefined item 3 is undefined item 3 is undefined
代码result.push( function() {alert(item + ' ' + list[i])} ), 使result数组添加了三个匿名函数的引用。这句代码也可以写成 var p = function() {alert(item + ' ' + list[i])}; result.push(p); |
关于为什么会输出三次都是 "item 3 is undefined"
在上面的例子say667()例子中已经解释过了。
匿名函数function() {alert(item + ' ' + list[i])}中的list[i]并不是经过拷贝,而是对参数list的一个引用。直到函数buildList()返回为止,也就是说,返回最后一个引用。即遍历完list(注:list的最大下标应该是2)后,经过i++也就变成了3,这也就是为什么是item 3,而list[3]本身是没有初始化的,自然也就是undefined了。
例5。
以下是引用片段: <script type="text/javascript"> function newClosure(someNum, someRef) { // Local variables that end up within closure var num = someNum; var anArray = [1,2,3]; var ref = someRef; return function(x) { num += x; anArray.push(num); alert('num: ' + num + '\nanArray ' + anArray.toString() + '\nref.someVar ' + ref.someVar); } } var closure1 = newClosure(40, {someVar:' never-online'}) var closure2 = newClosure(99, {someVar:' BlueDestiny'}) closure1(4) closure2(3) </script> |
在这最后一个例子中,展示如何声明两个不同的闭包。
分享到:
相关推荐
在Java中,你可以使用Lambda表达式或匿名内部类来创建闭包,而在JavaScript中,所有的函数都是闭包。在C#中,可以使用`Action`、`Func`等委托类型或`lambda`表达式来创建闭包。 总的来说,闭包在编程中扮演着至关...
在深入讨论JavaScript闭包之前,首先需要了解JavaScript的变量作用域。在JavaScript中,变量的作用域分为两种:全局变量和局部变量。全局变量是在函数外部定义的变量,可以在JavaScript程序的任何地方被访问。局部...
本篇文章主要探讨JavaScript函数式编程中的一个重要概念——闭包(closure)。闭包是一种特殊的函数,它能记住其定义时的作用域,即使在函数执行完毕后,仍然可以访问到该作用域内的变量。在JavaScript中,每个函数...
理解并掌握JavaScript闭包是成为专业前端开发者的关键一步。在实际开发中,合理利用闭包可以提高代码的复用性和可维护性,同时也能避免一些常见的编程陷阱。通过深入学习和实践,可以更好地运用闭包这一强大的工具来...
资源名称:javascript闭包详解 中文word版 内容简介: Javascript中有几个非常重要的语言特性——对象、原型继承、闭包。其中闭包 对于那些使用传统静态语言C/C 的程序员来说是一个新的...
闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现。
通过以上对JavaScript闭包的详细介绍,希望读者能够更好地理解闭包的概念,以及如何在实际的编程工作中利用闭包来解决具体问题。闭包是JavaScript中一项高级特性,深入掌握闭包将能够显著提升JavaScript编程能力。
在JavaScript中,闭包(Closure)是一个极其关键的概念,它使得内部函数能够访问到其外部函数的作用域内的变量,即使外部函数已经执行完毕。这一特性是基于JavaScript的函数作用域规则以及函数本身可以作为值进行...
Javascript中有几个非常重要的语言特性——对象、原型继承、闭包。其中闭包 对于那些使用传统静态...本文将以例子入手来介绍Javascript闭包的语言特性,并结合一点 ECMAScript语言规范来使读者可以更深入的理解闭包。
描述:详细描述JavaScript闭包,适合更进一步了解闭包。 标签:javascript 闭包 从给定的文件信息来看,主要围绕JavaScript中的闭包概念进行深入探讨。闭包是计算机科学中一个重要的概念,特别是在函数式编程语言...
闭包(Closure)是JavaScript中的另一个重要概念,是指函数和声明该函数的词法环境的组合。闭包允许一个函数访问并操作函数外部的变量。闭包的形成离不开函数嵌套和函数作为返回值的使用。闭包的优点是可以保存状态...
本书是关于JavaScript闭包的深度解析与应用实践的权威之作,深入探讨了闭包在JavaScript中的各种应用场景和技术细节。 **作者简介:** Michael Bolin是一位资深的软件工程师,拥有多年的编程经验,专注于...
在深入探讨闭包之前,我们首先需要理解JavaScript中变量的作用域。在JavaScript中,变量的作用域主要分为全局变量和局部变量。全局变量在任何地方都是可见的,而局部变量只在声明它的函数内可见。JavaScript函数的...
闭包在JavaScript中是一个至关重要的概念,它涉及到函数、作用域和变量持久化的特性。闭包的本质是一个函数,这个函数可以访问并操作其外部函数作用域内的变量,即使外部函数已经执行完毕,这些变量仍然会被保留。这...
### JavaScript闭包高级教程 #### 简介 在JavaScript编程中,“闭包”是一个非常重要的概念,尤其对于希望深入理解和高效使用JavaScript的开发者来说。简单地说,闭包是一种能够记住并访问其创建时周围环境的函数...
本文提供了基于闭包的JavaScript面向对象编程框架的设计和实现,展示了闭包在JavaScript中实现基于类的面向对象编程的可能性。 知识点: 1. 闭包(Closure)是一种JavaScript编程技术,用于实现基于类的面向对象...