闭包对于学习javascript的同学们来说,是不可避免要谈到的一个概念。
开始接触javascript的时候,对它也是很难理解的,令人生畏,一直疑问,到底什么才是闭包呢?那么我们如何能快速熟练地掌握javascript闭包呢?
相信大家在网上看过不少关于闭包的资料。
那么闭包真的有那么可怕吗?它没有想象中的可怕,其实,要理解闭包我们只需学会三个基本的事实即可。
1、js允许你引用在当前函数以外定义的变量
2、即使外部函数已经返回,当前函数仍然可以引用在外部函数所定义的变量。
3、闭包可以更新外部变量的值。
下面分别用实例代码来说明以上三个事实。
一、第一个事实:js允许你引用在当前函数以外定义的变量
function studyClosure(){ var myName="闭包"; function study(face){ return myName+face; } return study("你好啊"); } studyClosure(); // "闭包你好啊"myName是定义在外部studyClosure函数内的变量,也就是说myName是study函数以外的变量。请注意study是如何引用到的。
二、第二个事实:即使外部函数已经返回,当前函数仍然可以引用在外部函数所定义的变量。
function studyClosure(){ var myName="闭包"; function study(face){ return myName+face; } return study; } var b=studyClosure(); b("你好啊"); // "闭包你好啊" b("是谁?"); // "闭包是谁?"本例子中,在studyClosure()函数中返回的是study函数本身,而不像第一个例子中立即调用study(“你好啊”)。因此,b的值为内部的study(),也就是说调用b函数其实就是调用study函数。那么即使studyClosure函数已经返回了,study函数仍能记住myName的值。
对于这个,它的原理又是怎样的?
原理:js的函数值包含了比调用它们时执行所需要的代码还要多的信息。而且js函数值还在内部存储它们可能会引用的定义在其封闭作用域的变量。那些在其所涵盖的作用域内跟踪变量的函数被称为闭包。study函数就是一个闭包。其代码引用了两个外部变量:studyClosure和myName。每当study被调用时,其代码都能引用到这两个变量,因为该闭包存储了这两个变量。
函数可以引用在其作用域内的任何变量,包括参数和外部函数变量。我们可以利用这点来编写更加通用的studyCloseure函数。
function studyClosure(myName){ function study(face){ return myName+face; } return study; } var a=studyClosure("闭包"); a("你好啊"); //"闭包你好啊" a("是谁?"); //"闭包是谁?" var b=studyClosure("bibao"); b("a123"); //"bibaoa123" b("a234"); //"bibaoa234"本例子我们创建了a和b两个完全不同的函数。尽管他们都是由相同的study函数定义的,但是他们是两个截然不同的对象。第一个函数的myName的值为’闭包’,而第二个函数的myName的值为’bibao’。
闭包是js最优雅、最有表现力的特性之一,也是许多惯用法的核心。js还提供了一种更为方便构建闭包的字面量语法–函数表达式。
function studyClosure(myName){ return function(face){ return myName+face; } }
请注意,该函数表达式是匿名的。由于我们只需要其能产生一个新的函数值,而不打算在局部调用它,因此根本没有必要给该函数命名。
function box(){ var val=undefined; return { set:function(newVal){val=newVal}, get:function(){return val}, type:function(){return typeof val} } } var b=box(); b.type();//"undefined" b.set(88.8); b.get();//88.8 b.type();//"number"这个例子里产生了一个包含三个闭包的对象。这三个闭包是set,get和type属性。它们共享访问val变量。set闭包更新val的值,随后调用get和type查看更新的结果。
提示:
- 函数可以引用定义在其外部作用域的变量
- 闭包比创建它们的函数有更长的生命周期
- 闭包在内部存储其外部变量的引用,并能读写这些变量
本文章是摘自Effective JavaScript第11条之熟练掌握闭包,是学习的一个笔记记录。版权归原作者所有,只用于交流与学习的目的。