闭包的使用场景


在讲解闭包之前,我们需要先了解作用域这一概念。作用域代表了一个变量合法的使用范围。
举例说明:

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)
被面试官问到什么是闭包,最好的回答就是把本文中的前两个 demo 写一遍,然后说出闭包的使用场景【cache缓存 setTimeout定时器 异步操作 等】。不用说什么概念。

相关