JS闭包
闭包是什么
一个函数和对其周围状态(lexical environment,词法环境)的引用捆绑在一起(或者说函数被引用包围),这样的组合就是闭包(closure)
也就是说,闭包让你可以在一个内层函数中访问到其外层函数的作用域
在 JavaScript
中,每当创建一个函数,闭包就会在函数创建的同时被创建出来,作为函数内部与外部连接起来的一座桥梁
1 2 3 4 5 6 7 8
| function init() { var name = "Mozilla"; function displayName() { alert(name); } displayName(); } init();
|
displayName()
没有自己的局部变量。然而,由于闭包的特性,它可以访问到外部函数的变量
使用场景
任何闭包的使用场景都离不开这两点:
柯里化函数
柯里化的目的在于避免频繁调用具有相同参数函数的同时,又能够轻松的重用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| function getArea(width, height) { return width * height }
const area1 = getArea(10, 20) const area2 = getArea(10, 30) const area3 = getArea(10, 40)
function getArea(width) { return height => { return width * height } }
const getTenWidthArea = getArea(10)
const area1 = getTenWidthArea(20)
const getTwentyWidthArea = getArea(20)
|
使用闭包模拟私有方法
在JavaScript
中,没有支持声明私有变量,但我们可以使用闭包来模拟私有方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| var Counter = (function() { var privateCounter = 0; function changeBy(val) { privateCounter += val; } return { increment: function() { changeBy(1); }, decrement: function() { changeBy(-1); }, value: function() { return privateCounter; } } })();
var Counter1 = makeCounter(); var Counter2 = makeCounter(); console.log(Counter1.value()); Counter1.increment(); Counter1.increment(); console.log(Counter1.value()); Counter1.decrement(); console.log(Counter1.value()); console.log(Counter2.value());
|
上述通过使用闭包来定义公共函数,并令其可以访问私有函数和变量,这种方式也叫模块方式
两个计数器 Counter1
和 Counter2
是维护它们各自的独立性的,每次调用其中一个计数器时,通过改变这个变量的值,会改变这个闭包的词法环境,不会影响另一个闭包中的变量