Open logan70 opened 4 years ago
MDN对闭包描述如下:
A closure is the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment).
闭包是函数和创建函数的环境的组合。
由 标准 可知,JavaScript中函数被创建时都会记录当前词法环境,所以说JavaScript中,每次创建函数,都会生成闭包。
从技术层面说,静态作用域(词法作用域)是通过闭包实现的。
这样就实现了静态作用域(词法作用域),也就是在编写代码时就能确定变量的解析过程。
我们常说的闭包,也可以说是“有意义”的闭包,具备以下两点特征:
最常见的闭包就是父函数内返回一个函数,返回函数内引用了父函数内变量:
const scope = 'outer' const genClosure = () => { const scope = 'local' return () => { console.log(scope) } } const closure = genClosure() closure() // <- 'local'
任何关于闭包的应用总结起来都离不开以下两点:
柯里化:把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数。
// 柯里化前 const getVolume = (l, w, h) => l * w * h const volume1 = getVolume(100, 200, 100) const volume2 = getVolume(100, 200, 300) // 柯里化后 const getVolume = l => w => h => l * w * h const getVolumeWithDefaultLW = getVolume(100)(200) const volume1 = getVolumeWithDefaultLW(100) const volume2 = getVolumeWithDefaultLW(300)
用于将内部实现封装,仅对外暴露接口,常见于工具库的开发中。
var counter = (function() { var privateCounter = 0 function changeBy(val) { privateCounter += val } return { increment: function() { changeBy(1) }, decrement: function() { changeBy(-1) }, value: function() { return privateCounter } } })()
最典型的就是ES6之前for循环中使用定时器延迟打印的问题。
for (var i = 1; i <= 3; i++) { setTimeout(function() { console.log(i) }, i * 1000) } // <- 4 // <- 4 // <- 4
使用立即执行函数,将i作为参数传入,可保存变量i的实时值。
for(var i = 1; i <= 3; i++){ (i => { setTimeout(() => { console.log(i) }, i * 1000) })(i) } // <- 1 // <- 2 // <- 3
闭包的实现原理和作用
闭包是什么
MDN对闭包描述如下:
闭包是函数和创建函数的环境的组合。
由 标准 可知,JavaScript中函数被创建时都会记录当前词法环境,所以说JavaScript中,每次创建函数,都会生成闭包。
闭包的作用
从技术层面说,静态作用域(词法作用域)是通过闭包实现的。
这样就实现了静态作用域(词法作用域),也就是在编写代码时就能确定变量的解析过程。
我们常说的闭包是什么
我们常说的闭包,也可以说是“有意义”的闭包,具备以下两点特征:
最常见的闭包就是父函数内返回一个函数,返回函数内引用了父函数内变量:
闭包的应用
任何关于闭包的应用总结起来都离不开以下两点:
函数柯里化和偏函数
柯里化:把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数。
模块化
用于将内部实现封装,仅对外暴露接口,常见于工具库的开发中。
模拟块级作用域
最典型的就是ES6之前for循环中使用定时器延迟打印的问题。
使用立即执行函数,将i作为参数传入,可保存变量i的实时值。