说起闭包,一般是 两个问题:
- 什么是闭包;
- 闭包的作用是什么;
首先说一下什么是闭包
(function() {
let local = '变量';
function foo(){
console.log(local)
}
})()
这段代码中,自执行函数中,有一个局部变量 local, 有一个函数 foo , foo 函数可以访问到其所在作用域的变量 local,这就形成了一个闭包
下面是 MDN 对闭包的定义
函数与对其状态即词法环境(lexical environment)的引用共同构成闭包(closure)
也就是说 闭包可以从函数内部访问到外部函数的作用域,注意这个作用域不是所有的外部作用域,而是函数所在的词法作用域。
通常情况下,我们说闭包最多的是这样的:
函数嵌套函数,然后 return 一个函数
比如这样:
function foo(){
var local = 1
function bar(){
local++
return local
}
return bar
}
var func = foo()
func()
这里面确实有闭包,local 变量和 bar 函数就组成了一个闭包。
但是为什么需要函数嵌套函数呢,为什么要 return 一个函数呢?
函数嵌套函数,是要产生一个局部作用域(这里就是外层函数的函数作用域),在这个作用域内,函数 bar 引用了bar 函数外部的其所在词法作用域内的变量 local;函数 bar 对其外部作用域的引用 就构成了 闭包。而return bar 是为了使用这个闭包,把 return bar 改为 window.bar = bar 也是一样的,只要让外部能访问到这个 bar 函数就可以了,这使得这个函数在定义时的词法作用域以外的地方被调用。所以说 闭包使得函数可以继续访问定义时的 词法作用域。
当然,无论使用何种方式对函数类型的值进行传递,当函数在别处被调用时都可以观察到 闭包。
function foo() {
let a= 11;
function bar() {
console.log(a) //11
}
baz(bar)
}
function baz(fn) {
fn() // 这就是闭包
}
将内部函数 bar 传递给外部函数 baz , 当调用这个内部函数 fn 时,它涵盖foo作用域的闭包就体现出来了,因为它可以访问到 到 foo 作用域内部的变量 a.
当然,传递函数当然也可以是间接的:
let fn;
function foo() {
let a= 11;
function bar() {
console.log(a) //11
}
fn = bar;
}
foo();
fn() // 这就是闭包
说明了 无论通过何种方式将 内部函数 传递到所在作用域以外,它都会持有原始定义的作用域的引用,无论在何处执行这个函数都将使用闭包。
闭包的作用
闭包常常用来 【间接访问一个变量】,换句话说就是:【隐藏一个变量】或者【封装变量,收敛权限】
比如验证一个用户是否是第一次登录
function isFirstLoad() {
var _list = []
return function(id) {
<!--_list 为自由变量-->
if(_list.indexOf(id) >= 0) {
return false
} else {
_list.push(id)
return true
}
}
}
var firstLoad = isFirstLoad()
firstLoad(10) // true
firstLoad(10) //false
firstLoad(20) //true
firstLoad(20) // false
说起闭包,一般是 两个问题:
首先说一下什么是闭包
这段代码中,自执行函数中,有一个局部变量 local, 有一个函数 foo , foo 函数可以访问到其所在作用域的变量 local,这就形成了一个闭包
下面是 MDN 对闭包的定义
也就是说 闭包可以从函数内部访问到外部函数的作用域,注意这个作用域不是所有的外部作用域,而是函数所在的词法作用域。
通常情况下,我们说闭包最多的是这样的:
函数嵌套函数,然后 return 一个函数
比如这样:
这里面确实有闭包,local 变量和 bar 函数就组成了一个闭包。
但是为什么需要函数嵌套函数呢,为什么要 return 一个函数呢?
函数嵌套函数,是要产生一个局部作用域(这里就是外层函数的函数作用域),在这个作用域内,函数 bar 引用了bar 函数外部的其所在词法作用域内的变量 local;函数 bar 对其外部作用域的引用 就构成了 闭包。而return bar 是为了使用这个闭包,把 return bar 改为 window.bar = bar 也是一样的,只要让外部能访问到这个 bar 函数就可以了,这使得这个函数在定义时的词法作用域以外的地方被调用。所以说 闭包使得函数可以继续访问定义时的 词法作用域。
当然,无论使用何种方式对函数类型的值进行传递,当函数在别处被调用时都可以观察到 闭包。
将内部函数 bar 传递给外部函数 baz , 当调用这个内部函数 fn 时,它涵盖foo作用域的闭包就体现出来了,因为它可以访问到 到 foo 作用域内部的变量 a.
当然,传递函数当然也可以是间接的:
说明了 无论通过何种方式将 内部函数 传递到所在作用域以外,它都会持有原始定义的作用域的引用,无论在何处执行这个函数都将使用闭包。
闭包的作用
闭包常常用来 【间接访问一个变量】,换句话说就是:【隐藏一个变量】或者【封装变量,收敛权限】
比如验证一个用户是否是第一次登录