嗨~大家好,我是阿华今天又来跟大家聊聊~
词法环境(Lexical environment)、 变数环境(variable environment)
在查找变数时,javascript 所做的不仅仅是查看目前执行上下文的变数环境。每个执行上下文都有对其外部环境的引用,该外部环境称为词法环境。
变数环境是词法环境的一部分,是目前执行上下文的环境。
closure
(What)
闭包是 JavaScript 中一种重要的特性,
它指的是函数包裹函数时,内部函数有使用外部函数的作用域中的变数,即使外部函数已经执行完毕,依然保持对这些变数的引用。
(When)
闭包这种特性,在需要维持函数内部状态或在内部函数需要访问外部函数作用域的情况下就可以使用。
(Why)
闭包这种特性使得函数可以保持状态、延长变数生命週期,并且可以创建私有变数和函数,这对于开发非常有用。
(How)
当内部函数引用了外部函数的变数时,JavaScript 引擎会将这些变数的引用保留在内部函数的作用域鍊(scope chain -> Closure)中,即使外部函数已经执行完毕,这些变数仍然可以被内部函数访问和使用。
下面透过两个例子来说明闭包,保持状态、创建私有变数和方法
// 保持状态、延长变数生命週期function useState(initialState) { let state = initialState; // 本该被gc回收的变数现在被保存在内部函数的作用域鍊里 function getState() { return state; } function setState(updatedState) { state = updatedState; } return [getState, setState];}const [count, setCount] = useState(0);count(); // 0setCount(1);count(); // 1setCount(500);count(); // 500
// 需要实现私有函数或私有变数的时候(外部数据取不到属于他 scope 的值)var counter = (function () { var privateCounter = 0; function changeBy(val) { privateCounter += val; } return { increment: function () { changeBy(1); }, decrement: function () { changeBy(-1); }, getValue: function () { return privateCounter; }, value: privateCounter, };})();console.log(counter.getValue()); // logs 0counter.increment();console.log(counter.getValue()); // logs 1console.log(counter.value); // logs 0
虽然说闭包很好用,但也不是没有缺点。从记忆体的角度来看,闭包的缺点是显而易见的,由于闭包会让内部函数记得外部的变数,这可能会造成变数常驻在记忆体当中,如果使用过多可能会造成记忆体泄露 (memory leak),需要小心使用。
memory leak: 程式没能成功释放弃用的记忆体,造成效能的损失或是执行的失败。