javascript中的闭包

作者 likaiqiang 日期 2020-05-17
javascript中的闭包

词法作用域

词法作用域即静态作用域。一个函数在定义时其作用域就确定了,这个作用域就是词法作用域,我们可以利用chrome debug工具查看这个作用域。

function foo(){
var a = 123
function bar(){
var b = 100
console.log(a,b)
}
console.dir(bar)
}

foo()

image.png

bar函数的[[Scopes]]属性是一个类数组,表示的就是bar函数在创建时的词法作用域,它的第零个值Closure,浏览器已经告诉我们这是一个闭包了。也就是说闭包实际上是一种特殊的作用域,归属于一个函数的词法作用域。

闭包的神奇之处

我们把上面的例子改一下,来看一下闭包是多么神奇。

function foo(){
var a = 123
function bar(){
var b = 100
console.log(a,b)
}
return bar
}

var bar = foo()

bar()

foo函数已经执行完毕,按理说a变量已经被销毁,但是bar的作用域链中仍然可以找到a,这就是闭包。一个函数在创建时会创建词法作用域,这时候可能会产生闭包,该函数在其词法作用域外执行时闭包(如果有)就起作用了。这就是困惑很多人多年的闭包概念,是不是很简单。。。

一个函数在创建时就有可能产生闭包,而javascript中函数又是一等公民,所以让一个函数在其词法作用域外运行简直太容易了。闭包在javascript中到处都是。

var createObj(name){
var obj = {}
obj.sayName = ()=>{
console.log(name)
}
return obj
}
function bind(func,context,..arg){
return function(){
func.apply(context,[...arg,...arguments])
}
}
function foo(){
var btn = document.getElementById('btn')
var count = 0
function onClick(){
count++
console.log(count)
if(count>6)
btn.removeEventListener('click',onClick)
}
btn.addEventListener('click',onClick)
}
foo()

以上这些都创建了闭包,都符合函数在其词法作用域外运行的规律。是不是有种“不识庐山真面目,只缘身在此山中”的感觉。