web前端面试题js闭包理解_第1页
web前端面试题js闭包理解_第2页
免费预览已结束,剩余1页可下载查看

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、一、闭包?”的解释是:闭包是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。相信很少有人能直接看懂这句话,因为他描述的太学术。其实这句话通俗的来说就是:JavaScript 中所有的 function 都是一个闭包。不过一般来说,嵌套的 function 所产生的闭包更为强大,也是大部分时候所谓的“闭包”。看下面这段代码:1 function a() 2 varvar c = a();7 c();i = 0; 3function b() alert(+i); 4return b;56这段代码有两个特点:1、函数 b 嵌套在函数 a;2、函数

2、a 返回函数b。关系如图:这样在执行完 var c=a()后,变量 c 实际上是指向了函数b,再执行 c()后就会弹出一个窗口显示 i 的值(第一次为 1)。这段代码其实就创建了一个闭包,为什么?因为函数 a 外的变量 c了函数a 内的函数b,就是说:当函数 a 的函数 b 被函数 a 外的一个变量的时候,就创建了一个闭包。让说的更透彻一些。所谓“闭包”,就是在构造函数体内定义另外的函数作为目标对象的方法函数,而这个对象的方法函数反过来外层函数体中的临时变量。这使得只要目标对象在生存期内始终能保持其方法,就能间接保持原构造函数体当时用到的临时变量值。尽管最开始的构造函数调用已经结束,临时变量的

3、名称也都了,但在目 标对象的方法。即使再次调用相同的构造内却始终能到该变量的值,而且该值只能通这种方法来函数,但只会生成新对象和方法,新的临时变量只是对应新的值,和上次那次调用的是各自独立的。二、变量的作用域要理解闭包,首先必须理解 Javascript 特殊的变量作用域。变量的作用域无非就是两种:全局变量和局部变量。Javascript 语言的特殊之处,就在于函数可以直接全局变量。下面通过一段代码来看一下1 var n=999;2function f1()3alert(n);45f1(); / 999另一方面,在函数外部自然无法函数内的局部变量。1 function f1()2var n=9

4、99;34alert(n); /error变量的时候,一定要使用 var 命令。如果不用的话,这里有一个地方需要注意,函数你实际上了一个全局变量!1 function f1()2n=999;34f1();5alert(n); / 999以上只是一个关于 javascript 变量作用域基础的例子。三、如何从外部局部变量?(闭包)有时候需要得到函数内的局部变量。但是,前面已经不到的,只有通过变通方法才能实现。了,正常情况下,这是办当然这个变通的方法便是使用闭包,下面再通过一个例子来看一下1 function f1()2 alert(n);5/ 999n=999;3return f2;7funct

5、ion f2()468var result=f1();9result();这个便是闭包的一个简单的例子。由于在 Javascript 语言中,只有函数的子函数才能局部变量,因此可以把闭包简单理解成“定义在一个函数部连接起来的一座桥梁。的函数”。所以,在本质上,闭包就是将函数和函数外和面有变量。象的语言相比,闭包便是使用对象中一个特定的公有函数去这个对象的私四、闭包的用途闭包可以用在许多地方。它的最大用处有两个,一个是前面提到的可以变量,另一个就是让这些变量的值始终保持在内存中。函数的怎么来理解这句话呢?请看下面的代码。1 function f1()var n=999;nAdd=function

6、()n+=1function f2()alert(n);return f2;var result=f1();result(); / 999nAdd();result(); / 1000在这段代码中,result 实际上就是闭包 f2 函数。它一共运行了两次,第一次的值是 999,第二次的值是 1000。这证明了,函数 f1 中的局部变量 n 一直保存在内存中,并没有在 f1调用后被自动清除。为什么会这样呢?原因就在于 f1 是 f2 的父函数,而 f2 被赋给了一个全局变量,这导致f2 始终在内存中,而 f2 的存在依赖于 f1,因此 f1 也始终在内存中,因为全局变量只有在代码执行完退出的时

7、候才清楚,所以 f1 不会在调用结束后,被collection)回收,而会一直存在直到程序退出。回收机制(garbage这段代码中另一个值得注意的地方,就是“nAdd=function()n+=1”这一行,首先在 nAdd前面没有使用 var 关键字,因此 nAdd 是一个全局变量,而不是局部变量。其次,nAdd 的值是一个函数(anonymous function),而这个函数本身也是一个闭包,所以 nAdd相当于是一个 setter,可以在函数外部对函数的局部变量进行操作。五、Javascript 的回收机制还是以这个图来说:在 Javascript 中,如果一个对象不再被,那么这个对象就

8、会被 GC 回收。如果两个对象互相数 a 被b,而不再被第 3 者所,那么这两个互相的对象也会被回收。因为函,b 又被a 外的 c,这就是为什么函数 a 执行后不会被回收的原因。六、使用闭包的1、由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能闭包,否则会造成网页的性能问题,在 IE 中可能导致内存前,将不使用的局部变量全部删除。解决方法是,在退出函数之2、闭包会在父函数外部,改变父函数变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把变量当作它的私有属变量的值。性(private value),这时一定要,不

9、要随便改变父函数七、思考题如果你能理解下面代码的运行结果,应该就算理解闭包的运行机制了。1 var name = The Window;2var object = 53name : My Object,4getNameFunc : function()return function()6return ;7;89 ;10alert(object.getNameFunc()(); /The Window上面例子中对象中 getNameFunc 方法使用了一个闭包,而这个返回的闭包中又包含了一个闭包返回 ,当执行 object.getNameFunc()()时,会

10、先到第一对圆括号执行 getNameFunc 函数,返回了一个闭包函数,然后再次读后面的圆括号,将这个闭包返回的函数执行,然后返回 ,这段代码里面相当于执行了两层闭包。1 function outerFun() 2 3 var a=0; 4 function innerFun() 5 6a+; 7alert(a); 8 9 return innerFun; /注意这里 10 11 var obj=outerFun();12 obj();/结果为 113 obj(); /结果为 214 var obj2=outerFun();15 obj2(); /结果为 116 obj2()

11、;/结果为 2上面的例子,当包 ,因为是在被外部函数在定义它的作用域的外部被时,就创建了该函数的闭是创建了一个闭包,所以当被外部两次的时候便会同时也创建两个闭包,每个闭包各不。如果函数了位于外部函数的变量,当外部函数调用完毕后,这些变量在内存不会被,因为闭包需要它们。八、闭包内的微观世界如果要更加深入的了解闭包以及函数 a 和嵌套函数 b 的关系,需要引入另外几个概念:函数的执行环境(excution context)、活动对象(call object)、作用域(scope)、作用域链(scope chain)。以函数 a 从定义到执行的过程为例阐述这几个概念。1.当定义函数a 的时候,js

12、解释器会将函数 a 的作用域链(scope chain)设置为定义 a时 a 所在的“环境”,如果a 是一个全局函数,则scope chain 中只有 window 对象。当执行函数a 的时候,a 会进入相应的执行环境(excution context)。在创建执行环境的过程中,首先会为 a 添加一个scope 属性,即a 的作用域,其值就为第 1 步中的scope chain。即 a.scope=a 的作用域链。然后执行环境会创建一个活动对象(call object)。活动对象也是一个拥有属性的对2.3.4.象,但它不具有原型而且不能通过 JavaScript 代码直接。创建完活动对象后,把

13、活动对象添加到 a 的作用域链的最顶端。此时 a 的作用域链包含了两个对象:a 的活动对象和window 对象。下一步是在活动对象上添加一个 arguments 属性,它保存着调用函数 a 时所传递的参数。5.6.最后把所有函数a 的形参和的函数b 的也添加到 a 的活动对象上。在这一步中,完成了函数 b 的的定义,因此如同第 3 步,函数 b 的作用域链被设置为 b 所被定义的环境,即a 的作用域。到此,整个函数 a 从定义到执行的步骤就完成了。此时 a 返回函数b 的给 c,又函数 b 的作用域链包含了对函数a 的活动对象的,也就是说b 可以到a 中定义的所有变量和函数。函数 b 被 c收。,函数 b 又依赖函数a,因此函数 a 在返回后不会被 GC 回当函数b 执行的时候亦会像以上步骤一样。因此,执行时b 的作用域链包含了 3 个对象:b 的活动对象、a 的活动对象和window 对象,如下图所示:,当在函数b 中一个变量的时候,搜索顺序是:1.先搜索自身的活动对象,如果存在

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论