闭包的标准答案
作为常考的八股文,在网上有两种关于闭包的标准答案
答案1:闭包,能够读取其他函数内部变量的函数
答案2:闭包的本质就是在一个函数内部创建另一个函数
那么哪种答案是对的呢,其实两种答案都是对的,可以说是一种现象的不同解释。但是作为面试常用考点,其实回答其中之一的答案并不是最优解,因为面试官背的标准答案可能和你背的不是同一个。
因此,在面试之余可以深入挖掘一下闭包的关联概念,了解闭包的起源和真实的“标准答案”。
为什么会出现闭包
明明是一个函数,为什么要用用闭包这个名词来说明呢?
可以从一个最简单的表达式开始说起,表达式 1 + 1
,计算机能直接识别。
那么一个新的表达式 1 + X
如何执行呢?其中X
就是未决变量,执行就需要告诉计算机X
是什么。这样可以说就是一个函数了。
如果是一个参数,那么在js中就可以用箭头函数表示为(X) => { 1+ X}
。那么在数学上就可以用λX.1 + X
来表示X
为参数。同样用数学的lamda公式
也可以表示出函数。
那么如果有新的未决变量Y
,那么在数学上就可以表示为λX.Y + X
,那么这条语句因为计算机不能识别出来Y
的定义,因此是不能执行的。这就需要用到环境中的变量来定义这个Y
,让这个函数可以执行。那么闭包的概念就可以很明显的出来了:
闭包 = 环境(包含Y的环境) + 控制(λX.Y + X)
因此Javascript
为了实现闭包,把函数定义成了定义时候的环境。这当然不是闭包唯一的实现策略。
闭包的标准答案
闭包closure
是1964年提出的一个计算机编程的概念,按照当时论文《表达式的机器执行》的定义它包含控制和环境两个部分,在Javascript
中,以函数能够访问定义时的环境中变量的方式得以实现。
常用的闭包有哪些
除了上述闭包的概念外,还可以了解以下我们开发中用到了哪些闭包?
防抖
应用场景:一个搜索输入框,用户不停的进行输入(这个时候就是抖动的过程),等用户输入停止之后,再触发搜索
function debounce(fn, delay = 200) {
let timer = 0; // timer在返回的函数中被使用
return function () {
if (timer) {
clearTimeout(timer)
}
timer = setTimeout(() => {
fn.apply(this, arguments)
timer = 0
}, delay)
}
}
模拟模块(私有方法)
var Counter = (function() {
var privateCounter = 0 // 私有变量
function changBy(val) {
privateCounter += val
}
return {
intcrement: function() { // 三个闭包共用一个词法语境
changBy(1)
},
delcrement: function() {
changBy(-1)
},
value: function() {
return privateCounter
}
}
})()
console.log(Counter.value()) // 0