Why You Need JavaScript Closure
从头了解为什么你需要 JavaScript 闭包
从头说起
闭包可以让你在函数内获得函数外作用域的变量
但这么说很难理解,什么是作用域?为了更好地了解闭包,让我们从头说起。通常在函数内会使用两种方法来使用变量:
- 方法 A:将变量作为参数传入函数内
- 方法 B:在函数内定义一个变量
// 方法 Afunction add(a, b) { return a + b;}
// 方法 Bfunction sayHello() { const greeting = '你好'; return greeting;}但如果函数外想要访问函数内的变量是不行的,这是因为函数会创建一个新的作用域,让变量只能在函数内使用。
function sayHello() { const greeting = '你好'; return greeting;}
console.log(greeting); // ReferenceError: greeting is not defined但如果直接使用函数以外的变量会发生什么事?是可行的!这是因为前面提到的:「闭包可以让你在函数内获得函数外作用域的变量」,闭包只是一种形容这种特性的词汇,实际牵涉到 JavaScript 的作用域与底层的运行方式,才造就了闭包这种特性。
const greeting = '你好';function sayHello() { return greeting;}
console.log(sayHello()); // 仍旧可以打印出 你好
具体来说可以用 console.dir() 来观察该函数,会发现 sayHello 函数具备该函数作用域以外的数据,这份数据就算是在 sayHello 函数执行完成后,仍然可以访问到。
什么时候该使用闭包?
函数以外的作用域会持续存在,就算函数已经执行完毕
闭包需要更多的内存空间与运算,因此最好在真正需要的时候才使用这一特性,大多数时候会用于以下几种情况:
形成私有变量
闭包可以让函数内的变量不会被外部函数访问,因此可以用来形成私有变量。
function makeCounter() { let count = 0; // 外部无法访问到该变量
return function () { return (count += 1); };}
const counter = makeCounter();
console.log(counter()); // 1模块化
闭包可以用来搭配工厂模式,模块化代码,保存状态。
function makeCounter() { let count = 0;
return function () { return (count += 1); };}
const counterA = makeCounter();const counterB = makeCounter();
console.log(counterA()); // 1console.log(counterA()); // 2
console.log(counterB()); // 1console.log(counterB()); // 2