闭包(Closure)是一个老生常谈的话题,也是JavaScript重要的特性之一(闭包和异步)
说闭包之前我们先了解下作用域(scopes)
作用域分为全局变量和局部变量。
在函数下定义var就会产生一个局部变量,否则就会创建一个全局变量。全局变量是一个定时炸弹,要小心对待。
可以开启严格模式检查 'use strict'
JavaScript有一个特性,外部的访问不到内部的,内部可以访问外部的。
var a = 0
;(function cope(){
var b = 1
console.log(a)// 0
})()
console.log(b)// defined
另一个作用域想要获取内部作用域变量,需要变通下。
var a = 0
;(function cope(){
var b = 1
console.log(a)//0
;(function test(){
console.log(b)// 1
})()
})()
上面的代码里,test嵌套在cope里面,test可以访问cope里面的变量,那么就是闭包么,也许是吧,但确切说并不是。
为什么说是,因为test嵌套在cope函数里面,test可以访问到cope的代码。
为什么说不是,因为这只是满足了一部分闭包的一部分规则,但这是最重要的。
那什么是闭包
var c = (function(){
var _var = 0
function test(){
console.log(_var)
}
return test
})()
c()// 妈妈,你看这就是闭包
对比上面的代码,有什么变化? 对,就是return回去,然后实际调用。
test函数在外部调用,闭包可以继续享受定义时的语法作用域。
注意:闭包创建完之后,this是window
闭包可以有效防止变量冲突,还有一个常用的是立即执行函数(IIFE)
如上面的代码
// 显示函数请用(function(){})() 的写法,不然外部调用不到
;!function(){
// lalalalalala
}()
我们利用IIFE来解决不希望copes发生的事情。
var arr = []
for(var i=0; i < 10; i++){
arr[i] = function(){
console.log(i)
}
}
arr[0]() // 10 纳尼?妈妈,这是怎么回事?
妈妈:因为所有函数共享同一个[[Scope]]
试着用IIFE得到真确的值:
var arr = []
for(var i=0; i < 10; i++){
;(function(i){
arr[i] = function(){
console.log(i)
}
})(i)
}
arr[0]()
严格来说IIFE并不是闭包。
写一个柯里化玩玩
function a(){
var i = 0
function init(v){
i = v+i
console.log(i)
return init
}
return init
}
var a = a()
更多实例请看开源的库,比如书生写的XXY
如遇到错误,恳请批评指正,谢谢!
---END--