什么是闭包?官方给出的解释就是有权方访问另一个函数内部的参数的函数;这么理解是不错的,但是如果想要很好的理解闭包的本质就需要知道JS的解析过程、作用域及作用域链、垃圾回收机制
了解了以上这些我们知道, js的闭包是js运行机制下的必然结果 ;接下来我们看一个简单的闭包实例,然后从这个实例来理解闭包到底是怎么产生的
1 2 3 4 5 6 7 8 9 |
var num = 222; function a(){ var num = 666; return function b(){ return num } } console.log(num);//222 console.log(a()());;//666 |
闭包的实际产生过程:我们在全局创建变量num的时候,解释器会查看全局作用域下有没有这个变量,如果有就忽略,如果没有就创建一个变量,并赋值undefined;在全局创建以函数a的时候,解释器也会查看全局作用域有没有这个函数,如果有就忽略,如果没有就开始创建函数a;创建函数在词法分析的时候,就产生了一个作用域,在预解析阶段生成了一个作用域链,这个作用域链上包含一个全局的活动对象,当运行函数a的时候,会把当前的活动对象推入到这个作用域链上,这个时候函数a的作用域链就包含当前活动对象和全局活动对象;当函数a里的函数b运行的时候,把函数b活动对象推入到函数b作用域链上,这个给时侯函数b的作用域链就是函数b活动对象,函数a活动对象和全局活动对象,当函数b结束的时候会删除函数b的活动对象,作用域链上还有函数a活动对象和全局活动对象,这个时候函数b被抛出给了全局作用域下,垃圾回收机制无法清除函数a,函数a里的变量就被保留下来,这就形成了闭包
闭包面试题:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
//Q1 function fun(n,o) { console.log(o); return { fun:function(m){ console.log(n); return fun(m,n); } }; } var a = fun(0); a.fun(1); a.fun(2); a.fun(3);//?,?,?,? var b = fun(0).fun(1).fun(2).fun(3);//?,?,?,? var c = fun(0).fun(1); c.fun(2); c.fun(3);//?,?,?,? //Q2 for (var i = 1; i <= 5; i++) { setTimeout( function timer() { console.log(i); }, 1000 ); } for (var i = 1; i <= 5; i++) { (function(i){ setTimeout( function timer() { console.log(i); }, 1000 ); })(i); } |