作用域、作用域链
- 运行期上下文(AO):函数执行时会创建一个称为执行期上下文的内部对象
- 一个AO定义了一个函数执行时的环境
 - 函数每次执行时创建新的AO,多次调用函数会创建多个AO,
 - 函数每次执行时,将新生成的AO放到作用域链的最顶端,函数执行完时被销毁
 
 - 作用域:
- [[scope]]:作用域存储了运行期上下文的集合
 - 作用域链:[[scope]]中存储的运行期上下文对象的集合,集合呈链式连接
查找变量:从作用域链顶端依次向下查找
(./demo/js/闭包.html) 
 
<script>function a() {console.log(a); // undefinedconsole.log(b); // function bfunction b() {var b = 234;console.log(b); //234}console.log(b); //function bvar a = 123;console.log(a); // 123return b;}var glob = 100;var demo = a();demo();</script>/*作用域链:a被定义时“./img/作用域链1.png”, a defined a.[[scope]] --> 0:GOa被执行时,b被定义“./img/作用域链2.png”, a activated a.[[scope]] --> 0:aAO1: GOb defined b.[[scope]] --> 0:aAO1: GOb被执行“./img/作用域链3.png” b activated b.[[scope]] --> 0: bAO1: aAO2: GO*/
- 闭包
- a被执行时,b被定义,同时b被demo保存
 - a被销毁时,b仍然存在,“./img/闭包.png”
 - 因此可以在外部通过函数demo访问a中的变量
 
 
闭包
函数A内申明并保存在外部(被外部变量指向),可通过函数B使用A内部的局部变量或形参。外界对A函数内变量的引用导致其作用域不能被释放,构成一个闭包。
function Counter() {let num = 0;return {add() {num++;console.log(num);}}}let counter = Counter();Counter.add() // 1Counder.add() // 2
闭包的作用
- 做缓存(存储结构)
 - 模块化开发,防止污染全局变量
 - 实现封装
 
// 封装 类 数据结构function cache = !() => {const store = {};return {get(key) {return store[key];}set(key, val) {store[key] = val;}remove(key) {delete store[key];}}}console.log(cache);cache.set('name': 'nini');cache.get('name'); // 'nini'
- 暂存数据
 
// 将多个函数存储到数组中function test(){var arr = [];for(var i = 0; i < 10; i++) {(function(j){arr[j] = function(){document.write(j+'');}(i));}return arr;}var myArr = test();for(var j = 0; j < 10; j++) {myArr[j]();}
闭包的缺点
闭包内存得不到释放,容易造成内存泄漏
