作用域
function a() {
function b() {
}
b();
}
a();
// a 被定义 --> a.[[scope]] ---> [ 0: GO{} ]
// a 执行时 --> a.[[scope]] ---> [ 0: AO{}, 1: GO{} ]
// a 函数被定义时在 a.[[scope]] 属性中生成了一个 第0位 为 GO{}
// a 函数被执行时在 a.[[scope]] 属性中生成了一个 第0位 为 AO{} , 第1位 为 GO{}
// b 被定义 --> b.[[scope]] ---> [ 0: a的AO{}, 1: GO{} ]
// b 执行时 --> b.[[scope]] ---> [ 0: b的AO{}, 1: a的AO{}, 2: GO{} ]
// 在函数里查找变量,就从该函数的作用域链(a.[[scope]]存的是a的作用域链)的顶端向下查找,即从 a.[[scope]] 的 第0位 往后查
闭包
内部函数保存到外部一定产生闭包,会导致作用域链(不释放就是b中保存了a的AO)不释放,造成内存泄漏(相当于内存占用过多,剩下的内存变少)
// GO{ // a: function a(){ /* CODE */}, // glob: undefined, // demo: undefined // } // 执行后GO{ // a: function a(){ /* CODE */}, // glob: 100, // demo: a() // } function a(){ function b(){ var bbb = 234; console.log(aaa); // 123 console.log(demo); // function b(){ /* CODE */} } var aaa = 123; return b; } var glob = 100; var demo = a(); // aAO{ // aaa: undefined, // b: function b(){ /* CODE */} // } // a执行后aAO{ // aaa: 123, // b: function b(){ /* CODE */} // } demo(); // bAO{ // bbb: undefined, // } // b的执行bAO{ // bbb: 234, // }
- 练习01:
function a(){ function b(){ num++; console.log(num); } var num = 0; return b; } var demo = a(); demo(); // 1 demo(); // 2
闭包作用
- 累加器 --> 如上例
- 缓存(存储结构) 外部不可访问,内部确实存在的 --> 如上例的 num
- 模块化开发,防止污染全局变量
// 练习02: function test() { var num = 100; function a() { num++; console.log(num); } function b() { num--; console.log(num); } return [a, b]; } var arrFun = test(); arrFun[0](); // 101 操作的是test的AO arrFun[1](); // 100 因为操作的还是test的AO arrFun[0](); // 101 因为操作的还是test的AO arrFun[1](); // 100 因为操作的还是test的AO
- 将下面程序改成0-9的数组(只允许动两行,不能修改源代码中的字母符号,只能添加)
function test(){ var arr = []; for(var i = 0;i < 10;i++){ arr[i] = function(){ return i } } return arr } var myArr = test(); console.log(myArr[0]()); // 10 // ===> function test(){ var arr = []; for(var i = 0;i < 10;i++){ arr[i] = (function(i){ return i }(i)) } return arr } var myArr = test(); console.log(myArr); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
// 累加器: function add(){ var num = 0; function a(){ console.log(++num); // ==> num = num + 1; console.log(num); } return a; } var myAdd = add(); myAdd(); // 1 myAdd(); // 2 myAdd(); // 3
var x = 1; if(function f(){ }){ // (function f(){}) 括号将内部变成了表达式,用完 f就消失了 x += typeof f; } console.log(x); // 1undefined