在Javascript中,什么是闭包(Closure)

javascript

闭包的两个特点:

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 >生成 - setupSomeGlobals()</button>
<button >输出值 - gAlertNumber()</button>
<button >增加 - gIncreaseNumber()</button>
<button >赋值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>
在这最后一个例子中,展示如何声明两个不同的闭包。

时间: 2024-11-08 18:27:07

在Javascript中,什么是闭包(Closure)的相关文章

JavaScript中的闭包(Closure)详细介绍_javascript技巧

闭包是JavaScript中一个重要的特性,其最大的作用在于保存函数运行过程中的信息.在JavaScript中,闭包的诸多特性源自函数调用过程中的作用域链上.   函数调用对象与变量的作用域链   对于JavaScript中的每一次函数调用,JavaScript都会创建一个局部对象以储存在该函数中定义的局部变量:如果在该函数内部还有一个嵌套定义的函数(nested function),那么JavaScript会在已经定义的局部对象之上再定义一个嵌套局部对象.对于一个函数,其内部有多少层的嵌套函数

浅谈javascript中的闭包

  Javascript中有几个非常重要的语言特性--对象.原型继承.闭包.其中闭包 对于那些使用传统静态语言C/C++的程序员来说是一个新的语言特性.本文将以例子入手来介绍Javascript闭包的语言特性,并结合一点 ECMAScript语言规范来使读者可以更深入的理解闭包. 很长一段时间不理解闭包,后来了解了作用域,以及this相关问题才理解了闭包相关知识. 闭包(closure),也是面试题常客.简单点来说就是函数嵌套函数. 函数作为返回值: ? 1 2 3 4 5 6 7 8 9 10

浅析 JavaScript 中的 “闭包”

#JavaScript closure(闭包) 闭包的概念 Wikipedia:In programming languages, closures (also lexical closures or function closures) are a technique for implementing lexically scoped name binding in languages with first-class functions. 译文:"在编程语言中,闭包(也词法闭包或函数闭包)是

JavaScript 中词法作用域、闭包与跳出闭包详解

Lexical Scope:词法作用域 functions are executed using the scope chain that was in effect when they were defined 一般来说,在编程语言里我们常见的变量作用域就是词法作用域与动态作用域(Dynamic Scope),绝大部分的编程语言都是使用的词法作用域.词法作用域注重的是所谓的Write-Time,即编程时的上下文,而动态作用域以及常见的this的用法,都是Run-Time,即运行时上下文.词法作

JavaScript中的闭包原理分析_javascript技巧

我们来看一个定义: Closure 所谓"闭包",指的是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分. 这说明了,JavaScript中的闭包是包含了上下文的函数,也就是说,这个函数的作用基础,是它所处的环境,这是不能超越的,跟线性代数是不是有一点似曾相识的感觉呢? 换个角度看,闭包的作用是为了实现OO.JavaScript中,没有像C++那样的public.private.protect属性标识, 建立起类比较困难."类

JavaScript中的作用域链和闭包_javascript技巧

作用域 全局作用域 局部作用域 作用域链 执行上下文 活动对象 闭包 闭包优化 JavaScript中出现了一个以前没学过的概念--闭包.何为闭包?从表面理解即封闭的包,与作用域有关.所以,说闭包以前先说说作用域. 作用域(scope) 通常来说一段程序代码中使用的变量和函数并不总是可用的,限定其可用性的范围即作用域,作用域的使用提高了程序逻辑的局部性,增强程序的可靠性,减少名字冲突. 全局作用域(Global Scope) 在代码中任何地方都能访问到的对象拥有全局作用域,以下几种情形拥有全局作

javascript闭包(Closure)用法实例简析_javascript技巧

本文实例讲述了javascript闭包(Closure)用法.分享给大家供大家参考,具体如下: closure被翻译成"闭包",感觉这东西被包装的太学术化.下面参考书本和网上资源简单探讨一下(理解不当之处务请留意). 1.什么是闭包 官方的回答:所谓"闭包",指的是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分. 看了上面的定义,如果你不是高手,我坚信你会和我一样愤怒的质问:这tmd是人话吗? 要理解闭包,还是代码

Javascript 中的类和闭包_js面向对象

有人说javascript也是面向对象的,只是它是prototype based,当然这只是概念上的区别,我不想讨论js是不是面向对象的,关键是想说明虽然javascript的类表现得很像其他语言中的类,但是内部的实现机理确不太一致,如果一味的把javascript中的类类比作其他语言中的类,有时候脑子会犯混. 先看一段简单的代码,一般教材上介绍如何新建一个类的时候都是这样的(当然还有更复杂的方法,不过本质上是一样的): 复制代码 代码如下: function MyClass(x) { this

JavaScript中消除闭包的一般方法介绍

 这篇文章主要介绍了JavaScript中消除闭包的一般方法介绍,本文直接给出了操作示例,需要的朋友可以参考下     JavaScript 的闭包是一个其主动发展的特性, 也是一个被动发展的特性. 也就是说, 一方面, JS 有了闭包能更好解决一些问题. 另一方面, JS 为了解决某些问题, 而不得不使用闭包勉强来解决问题. 前者这里不讨论, 如果 JS 闭包能更好的解决问题, 当然使用闭包更好. 我讨论的是后者, 是因为 JS 本身的限制, 而不得不磕磕绊绊地用闭包来解决的问题, 例如"变量

JavaScript中的闭包介绍

 这篇文章主要介绍了JavaScript中的闭包介绍,本文讲解了Javacript 闭包.Javscript 闭包与this.Javscript 闭包与读写变量等内容,需要的朋友可以参考下     所谓的闭包应该是指: 内部函数读取当前函数以外的变量,即创建时所处的上下文环境. 代码如下: function hello(){ var char = "hello,world"; function print(){ console.log(char); }; return print();