闭包的使用场景
在讲解闭包之前,我们需要先了解作用域这一概念。作用域代表了一个变量合法的使用范围。
举例说明:
a可以在最外层的红框内被使用,a1可以在第二层红框内被使用,a2 a3同理。若要在最外层的红框内使用a1 a2 a3 则会报错。
作用域分为:
- 全局作用域
- 函数作用域
- 块级作用域(ES6新增,大括号内【if/while】是一个块级作用域)
这也就引出了自由变量【当前作用域未定义的变量】的查找规则:
- 一个变量在当前作用域没有定义,但被使用了
- 向上级作用域,一层一层一次寻找,直至找到为止
- 如果到全局作用域都没找到,则报错 xx is not defined
所有的自由变量的查找,是在函数定义的地方,向上级作用域查找,不是在执行的地方!!!
目前上述的变量执行情况是正常情况—在哪定义就在哪执行。但是也存在作用域应用的特殊情况,有两种表现:
- 函数作为参数被传递
- 函数作为返回值被返回
第一种情况是在别处定义好的函数拿到这里使用;第二种情况是在这里定义好的函数拿到别处使用。这两种特殊情况就是闭包。
// 函数作为参数
function print(fn) {
const a = 200
fn()
}
const a = 100
function fn() {
console.log(a)
}
print(fn) // 100
// 函数作为返回值给
function create() {
const a = 100
return function () {
console.log(a)
}
}
const fn = create()
const a = 200
fn() // 100
接下来给出具体场景应用:
- 函数作为返回值,以cache缓存为例:
function createCache() {
const data = {} //闭包中的数据被隐藏,不被外界访问
return {
set: function (key, val) {
data[key] = val
},
get: function (key) {
return data[key]
}
}
}
const c = createCache()
c.set('a', 100)
console.log(c.get('a'))
- 函数作为参数被传递,以setTimeout定时器为例:
function fn() {
alert()
}
const func = fn()
// 第一个参数是一个函数,或者是一段执行的js代码,第二参数是第一个参数执行的时间间隔。
setTimeout(func, 1000)