JavaScript--闭包(Closure)

闭包(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--

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容