JavaScript 进阶(四)解密闭包closure
闭包(closure)是什么东西
我面试前端基本都会问一个问题"请描述一下闭包"。相当多的应聘者的反应都是断断续续的词,“子函数”“父函数”“变量”,支支吾吾的说不清楚。我提示说如果你表述不清楚你可以写一小段代码示例一下。这个基本都会,比如这样:
- function A() {
- var i = 0;
- return function(){return i++;}
- }
看得出来他知道什么叫闭包,但是却又不清楚,只知道这么个写法,但是却又不是足够熟悉。那么本文就来深入探讨一下,闭包到底是个什么东西。
从C语言开始
- int calc(int a, int b) {
- int tempA = a * a;
- int tempB = b * b;
- int c = tempA + tempB;
- return c;
- }
- int main() {
- int sum = calc(3, 4);
- return 0;
- }
当函数calc调用的时候,main函数将两个参数,3,4压栈,然后进入calc函数。calc函数中用两个局部变量tempA,tempB来保存它们的平方。计算完和之后,将平方和返回给main函数。那么calc返回之后,如何访问tempA,tempB呢?答案是没法访问。calc函数退栈之后,这俩局部变量销毁了。局部变量的生命周期就是在他所在的子函数执行的时候存在,执行完成之后就销毁,赤裸裸的兔死狗烹。所以局部变量经常被叫做临时变量,这确实名副其实。
再来讲闭包
闭包的特性
- //modue1
- var m1,m2,m3;
- function foo1(){...}
- function foo2(){...}
- //module2
- var s1,s2,s3;
- function sb1(){...}
- function sb2(){...}
代码中引入了这个两个JS文件module1和module2.如果变量,函数较多,万一出现重名了,别的模块的变量就会被莫名其妙的修改,那么一些匪夷所思的bug就会出来。为了避免重名,当然可以规定前缀,命名规范等等,但是这治标不治本。让开发人员麻烦不说,当模块变多,维护这种规范的难度就会明显上升。结合刚才的闭包的特性,所以我们可以吧代码改成这样:
- //modue1
- function module1(){
- var m1,m2,m3;
- function foo1(){...}
- function foo2(){...}
- return{
- "foo1":foo1,
- "foo2":foo2
- }
- }
- //module2
- function module2(){
- var s1,s2,s3;
- function sb1(){...}
- function sb2(){...}
- return{
- "sb1":sb1,
- "sb2":sb2
- }
- }
当使用一个模块的时候,调用这个模块对应的函数即可,顶层的名空间就是模块的名字,这样维护起来就会方便很多。当然,大型项目中的多模块协作用闭包是一个手段,还有一个手段就是面向对象,这个我以后的文章会讲到。
闭包的另外一个容易忽略的特性就是一个闭包内的变量会被这个闭包对应的所有子函数共享。说起来有点拗口,我们来举个例子:
- function test() {
- var array = [];
- for(var i = 0; i < 10; i++) {
- array[i] = function(){return i;}
- }
- return array;
- }
这段代码返回了一个数组,数组里面的每一个元素都是一个函数。那么有下面的测试代码:
- var a = test();
- a[0](); //返回几?
看起来它应该返回0啊。这个函数产生的时候i = 0。这就错了,事实上这个函数会返回10,并且这个数组里面所有的函数都返回10.为什么呢?刚才有提到,数组中的所有的函数共享一个闭包,就是test函数的局部变量i。当test执行完成之后,i是几呢?当然是10.所以数组中的函数就都返回10了。这个特性经常被刚接触闭包的程序员忽视。当制造闭包的函数中有循环,条件语句的时候,经常会出现错误。这个要小心了。
此外,闭包是可以嵌套的。相信如果你前面的内容看懂了的话,理解嵌套闭包就是易如反掌了,在此我不做赘述。
结束
JavaScript 进阶(四)解密闭包closure的更多相关文章
- JavaScript进阶(四)js字符串转换成数字的三种方法
js字符串转换成数字的三种方法 在js读取文本框或者其它表单数据的时候获得的值是字符串类型的,例如两个文本框a和b,如果获得a的value值为11,b的value值为9 ,那么a.value要小于b. ...
- 深入理解JavaScript闭包(closure)
最近在网上查阅了不少javascript闭包(closure)相关的资料,写的大多是非常的学术和专业.对于初学者来说别说理解闭包了,就连文字叙述都很难看懂.撰写此文的目的就是用最通俗的文字揭开Java ...
- javascript中的闭包(Closure)的学习
闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. 下面是我在网上通过学习阮一峰老师的笔记,感觉总结很不错,特记录于此. 一.变量的作用域 要理解 ...
- [转载]学习Javascript闭包(Closure)
学习Javascript闭包(Closure) 源地址: http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures ...
- javascript进阶课程--第三章--匿名函数和闭包
javascript进阶课程--第三章--匿名函数和闭包 一.总结 二.学习要点 掌握匿名函数和闭包的应用 三.匿名函数和闭包 匿名函数 没有函数名字的函数 单独的匿名函数是无法运行和调用的 可以把匿 ...
- 前端进阶必读:《JavaScript核心技术开发解密》核心提炼二
前言 最近读勒基本关于前端的数据<JavaScript核心技术开发解密>,<webpack从入门到进阶>...这几本书帮助到我更好的理解JS.webpack在前端技术领域中的作 ...
- JavaScript闭包(Closure)
JavaScript闭包(Closure) 本文收集了多本书里对JavaScript闭包(Closure)的解释,或许会对理解闭包有一定帮助. <你不知道的JavsScript> Java ...
- 【转】深入理解JavaScript闭包闭包(closure) (closure)
一.什么是闭包?"官方"的解释是:闭包是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分.相信很少有人能直接看懂这句话,因为他描述 ...
- JavaScript进阶系列01,函数的声明,函数参数,函数闭包
本篇主要体验JavaScript函数的声明.函数参数以及函数闭包. □ 函数的声明 ※ 声明全局函数 通常这样声明函数: function doSth() { alert("可以在任何时候调 ...
随机推荐
- swift:打造你自己的折线图
看到苹果Health里的折线图了吗.我们就是要打造一个这样的折线图.没看过的请看下图. 我们的主题在于折线图本身.其他的包括步数.日平均值等描述类的内容这里就不涉及了. 首先观察,这个图种包含些什么组 ...
- Javascript 学习 笔记一
1.操作 HTML 元素 如需从 JavaScript 訪问某个 HTML 元素,您能够使用 document.getElementById(id) 方法. 请使用 &qu ...
- sql substring charindex
substring(s1,int,int) 截取字符串,起始位置,截取个数,返回截取后的字符串 charindex(s1,s2)查找字符s1在s2中的位置.返回int位置 SELECT substri ...
- BZOJ 3544: [ONTAK2010]Creative Accounting( BST )
题意 : 一段序列 , 求一段子序列和取余 M 的最大值 其实是一道水题... 前缀和 , 然后就是找 ( sum( r ) - sum( l ) ) % M 的最大值 . 考虑一个 sum( r ) ...
- Hibernate入门之配置文件
<?xml version='1.0' encoding='utf-8'?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hi ...
- 四级流水线的8bit加法器
以流水线实现8bit 加法器. //date : 2013/8/23 //designer :pengxiaoen //function : module pipeline ( clock ,rese ...
- Stackful 协程库 libgo(单机100万协程)
libgo 是一个使用 C++ 编写的协作式调度的stackful协程库, 同时也是一个强大的并行编程库. 设计之初是为高并发分布式Linux服务端程序开发提供底层框架支持,可以让链接进程序的同步的第 ...
- stdcall、cdecl、fastcall、thiscall 、naked call的汇编详解
函数调用规范 当高级语言函数被编译成机器码时,有一个问题就必须解决:因为CPU没有办法知道一个函数调用需要多少个.什么样的参数.即计算机不知道怎么给这个函数传递参数,传递参数的工作必须由函数调用者 ...
- 【HTTP 2】HTTP/2 协议概述(HTTP/2 Protocol Overview)
前情提要 在上一篇文章<[HTTP 2.0] 简介(Introduction)>中,我们简单介绍了 HTTP 2. 在本篇文章中,我们将会了解到 HTTP 2 协议概述部分的内容. HTT ...
- CF(435D - Special Grid)dp
题目链接:http://codeforces.com/problemset/problem/435/D 题意:求三角形个数,三个点必须的白点上,而且三条边必须是横线,竖线或对角线,三条边上不同意出现黑 ...