我对Javascript闭包的一点点理解

标签: javascript 闭包 理解 | 发表时间:2011-08-07 17:12 | 作者:(author unknown) dZYflE9Uh7sPhuMdcCh6XjSnpJxRHzciSsHWoGK7lWFGNvoc
出处:http://www.iteye.com

前言

如果前端人员不懂Javascript闭包,那只能说他压根就没懂Javascript,只能算入门级。本篇主要是写本人对闭包的一些理解,欢迎拍板。

 

闭包概念

先引用一下官方解释:

 

A "closure " is an expression (typically a function) that can have free varuables together with an environment that binds those variables (that "closes" the expression)

 

用我的蹩脚英语翻译过来换成自己的理解就是:

 

1.闭包首先是一个表达式,通常这个表达式是一个函数。

2.闭包拥有一个环境,使得它能够拥有这个环境底下的这个许多变量。

 

闭包举例

可能上边解释还是有点抽象,那我拿实际的代码举个例子:

var name = "window";
			
function outer(){
	var name = 'outer';

	function inner(){
		return name;
	}

  return inner;
}

alert(outer()()); 

 

可以试着在浏览器运行一下这段script,会发现,弹出框内容为outer。

我先解释这个过程大致发生了什么,再联系前面说的两点说说我对闭包的理解。

首先第一行定义了name变量,很容易理解,name就是属于当前的浏览的页面吧!(实际name就是在当前window底下的全局变量,至于window是什么变量,不懂的话就把它当做是当前页面所在的环境吧)。

第2行-第12行我们定义了outer函数。

再看看第13行发生了什么,outer()()这是什么语法???那我们先分解来看吧,outer()一般是干嘛呢?当然是执行outer函数然后返回一个值咯。那在这里返回值是什么呢?inner!好,那就是说outer() == inner,应该同意吧?

于是乎outer()() == inner(),

所以最后alert出来的值将会是inner函数返回的值。

 

乱了乱了,不是说过,在一对括号{}里算是一个域,在这个域里边定义的东西,在离开这个域之后就会被销毁吗?

上面这个观点是对的,但是这个就是javascript闭包强大的地方:它把本来要销毁的一些变量给挽救回来,继续放在内存里边,让后边可以调用这个闭包来获取这些变量。

 

回到例子上吧,我们在outer函数里边定义了inner函数,如果说你最后不把它返回并且复制给变量,这个inner函数就会被销毁了,但是我们在第13行将它抛出去给外界执行了!!!于是js解释器知道它被暴露在外头了,不应该被销毁,所以就留住它的所在的环境,也就是outer的这个域。里边的name也被留下来了。

 

执行outer()之后,我们获取了刚刚说被暴露在外边的inner函数了,紧接着执行inner(),于是inner就开始找寻name变量了,我们知道inner所在的环境被嵌套了2层,inner->outer->window,当然啦,按照我们就近原则,我们肯定现在inner里边找name变量,发现找不到,于是到outer那个环境去找,此时找到了name,把name返回给inner()调用处alert出来。(这里可以思考一下脚本找寻变量的过程,就可以知道过多地访问全局变量会经常要把时间消耗在搜索过程,所以尽量避免过多地访问全局变量,至于怎么做,比较简单的就是采用一个局部变量记录该全局变量并替换成访问该局部变量)

 

例子跟概念的联系

我简单的把上述例子跟前面的解释联系起来:

1. 闭包首先是一个表达式,通常这个表达式是一个函数。

    例子中的inner函数就是这么一个表达式。

2. 闭包拥有一个环境,使得它能够拥有这个环境底下的这个许多变量。

    inner函数返回并提供给外界调用导致了inner会继续停留在内存,从而提供了一个环境可以访问outer里边的变量。

 

我的理解

按我理解,可以把闭包以及闭包的用法简单总结成以下:

1.闭包一般就是函数,并且定义在一个函数里边的。当然了,闭包还可以是一个对象的。如下代码:

function outer(){
	var name = 'outer';

	return {
		inner:function(){
			return name;
		}
	};

}

alert(outer().inner());

2.在函数里边定义函数不一定是闭包,而是应该将这个函数返回并且赋值给外界或者给外界执行这个闭包。

因为js解释器要知道到底要不要销毁域底下的东西,如果它发现外界持有这个闭包的引用,它就不会去销毁这个环境。

3.闭包允许外界访问函数里边的局部变量,例如outer里边的name变量。

4.运用闭包可以储存函数里边的变量,可以避免更多的全局变量定义而污染,我觉得可以简单的跟面向对象的封装进行类比。

5.闭包会导致变量跟一些引用停留在内存不被销毁,将会导致内存消耗。

 

本篇总结

对于Javascript,我认为它的闭包是其精华所在,使它变得更加灵活以及衍生了很多高级功能。关于闭包,网上有很多精彩的讲解,这里只是记录一下本人的理解,欢迎交流。阮一峰的学习Javascript闭包(Closure) 对闭包的讲解很不错,推荐阅读一下。



已有 0 人发表留言,猛击->>这里<<-参与讨论


ITeye推荐



相关 [javascript 闭包 理解] 推荐:

Javascript闭包

- - JavaScript - Web前端 - ITeye博客
闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. 下面就是我的学习笔记,对于Javascript初学者应该是很有用的. 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域无非就是两种:全局变量和局部变量. Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量.

我对Javascript闭包的一点点理解

- dZYflE9Uh7sPhuMdcCh6XjSnpJxRHzciSsHWoGK7lWFGNvoc - ITeye博客
如果前端人员不懂Javascript闭包,那只能说他压根就没懂Javascript,只能算入门级. 本篇主要是写本人对闭包的一些理解,欢迎拍板. A "closure " is an expression (typically a function) that can have free varuables together with an environment that binds those variables (that "closes" the expression).

用最通俗易懂的代码帮助新手理解javascript闭包

- - 博客园_首页
我同样也是个javascript新手,怎么说呢,先学的jquery,精通之后发现了javascript的重要性,再回过头来学javascript面向对象编程. 最近看了几篇有关javascript闭包的文章,包括最近正火的 汤姆大叔系列,还有《javascript高级程序设计》中的文章,……我看不懂,里面有些代码是在大学教科书中看都没看过的,天书一般.

JavaScript 闭包及其机制

- - CSDN博客Web前端推荐文章
首先要区分两个概念,一是匿名函数,一是闭包. 所谓匿名函数,就是创建函数没有给定函数名. 经常出现的包括函数表达式,就是定义一个匿名函数,然后将函数赋值给某个变量,而此时这个变量就相当于该函数的函数名,例如:. alert("Hi"); }; //注意这个分号 sayHi(); //调用函数. 还有一种常用匿名函数的情况是回调函数,如 JQuery 中常用到的:.

我从来不理解 JavaScript 闭包,直到有人这样向我解释它... - Java架构—月亮 - 博客园

- -
正如标题所述,JavaScript 闭包对我来说一直有点神秘,看过很多闭包的文章,在工作使用过闭包,有时甚至在项目中使用闭包,但我确实是这是在使用闭包的知识. 最近看国外的一些文章,终于,有人用于一种让我明白方式对闭包进行了解释,我将在本文中尝试使用这种方法来解释闭包. 在理解闭包之前,有个重要的概念需要先了解一下,就是 js 执行上下文.

正确理解javascript的this关键字

- BeerBubble - 三水清
javascript有this关键字,this跟javascript的执行上下文密切相关,很多前端开发工程师至今对this关键字还是模棱两可,本文将结合代码讲解下javascript的this关键字. 定义了一个person对象,对象中包含了name、gender属性,还包括了一个getName的方法,其作用是输出person对象的name.

高性能JavaScript模板引擎原理解析

- - 腾讯CDC
  随着 web 发展,前端应用变得越来越复杂,基于后端的 javascript(Node.js) 也开始崭露头角,此时 javascript 被寄予了更大的期望,与此同时 javascript MVC 思想也开始流行起来. javascript 模板引擎作为数据与界面分离工作中最重要一环,越来越受开发者关注,近一年来在开源社区中更是百花齐放,在 Twitter、淘宝网、新浪浪微博、腾讯QQ空间、腾讯微博等大型网站中均能看到它们的身影.

(转)全面理解面向对象的 JavaScript

- - JavaScript - Web前端 - ITeye博客
要掌握好 JavaScript,首先一点是必须摒弃一些其他高级语言如 Java、C# 等类式面向对象思维的干扰,全面地从函数式语言的角度理解 JavaScript 原型式面向对象的特点. 当今 JavaScript 大行其道,各种应用对其依赖日深. web 程序员已逐渐习惯使用各种优秀的 JavaScript 框架快速开发 Web 应用,从而忽略了对原生 JavaScript 的学习和深入理解.

理解JavaScript的单线程运行机制及setTimeout(fn,0)

- - JavaScript - Web前端 - ITeye博客
阮老师的链接: http://javascript.ruanyifeng.com/bom/timer.html. 一、为什么JavaScript是单线程. JavaScript语言的一大特点就是单线程,也就是说,同一个时间只能做一件事. 那么,为什么JavaScript不能有多个线程呢. JavaScript的单线程,与它的用途有关.