# 作用域 ### 练习 ``` var color = "blue"; function changeColor() { let anotherColor = "red"; function swapColors() { let tempColor = anotherColor; anotherColor = color; color = tempColor; // 这里可以访问color、anotherColor和tempColor } // 这里可以访问color和anotherColor,但访问不到tempColor swapColors(); } // 这里只能访问color changeColor(); ``` 分析上面的作用域链:
展开查看 * window * color * changecolor() * anothercolor * swapcolors() * tempcolor
### 垃圾回收机制 优化内存占用的最佳手段就是保证在执行代码时只保存必要的数据。如果数据不再必要,那么把它设置为null ,从而释放其引用。这也可以叫作解除引用 。这个建议最适合全局变量和全局对象的属性。 局部变量在超出作用域后会被自动解除引用 即 全局变量(GO) 不会被销毁,但是局部变量(AO)函数执行完后会被销毁 也可以手动销毁变量,即赋值为null 如下面的例子所示: ``` function createPerson(name){ let localPerson = new Object(); localPerson.name = name; return localPerson; } let globalPerson = createPerson("Nicholas"); // 解除globalPerson对值的引用 //globalPerson = null; ``` 解析:
展开查看 在上面的代码中,变量globalPerson 保存着createPerson() 函数调用返回的值。在createPerson() 内部,localPerson 创建了一个对象并给它添加了一个name 属性。然后,localPerson 作为函数值被返回,并被赋值给globalPerson 。localPerson 在createPerson() 执行完成超出上下文后会自动被解除引用,不需要显式处理。但globalPerson 是一个全局变量,应该在不再需要时手动解除其引用,最后一行就是这么做的。 不过要注意,解除对一个值的引用并不会自动导致相关内存被回收。解除引用的关键在于确保相关的值已经不在上下文里了,因此它在下次垃圾回收时会被回收。
### 闭包 闭包是指有权访问另一个函数作用域中的变量的函数。创建闭包的常见方式,就是在一个函数内部创建另一个函数。 ``` function a() { var x = 0; return function(y) { x = x + y; // return x; console.log(x); } } var b = a(); b(1); //1 b(1); //2 ``` 练习1: ``` function fn() { var max = 10; return function bar(x) { if (x > max) { console.log(x); } }; } var f1 = fn(); f1(15); ``` 练习2 ``` function init() { var name = "Mozilla"; // name 是一个被 init 创建的局部变量 function displayName() { // displayName() 是内部函数,一个闭包 alert(name); // 使用了父函数中声明的变量 } displayName(); } init(); ```
init() 创建了一个局部变量 name 和一个名为 displayName() 的函数。displayName() 是定义在 init() 里的内部函数,并且仅在 init() 函数体内可用。请注意,displayName() 没有自己的局部变量。然而,因为它可以访问到外部函数的变量,所以 displayName() 可以使用父函数 init() 中声明的变量 name 。
hrefs: https://blog.csdn.net/weixin_43586120/article/details/89456183 http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures.html ``` (function() { var m = 0; function getM() { return m; } function seta(val) { m = val; } window.g = getM; window.f = seta; })(); f(100); console.info(g()); ```
``` function fn(){ var arr = []; for(var i = 0;i < 5;i ++){ arr[i] = (function(i){ return function (){ return i; }; })(i); } return arr; } // 立即执行函数 每调用一次完成后就自动销毁 var list = fn(); for(var i = 0,len = list.length;i < len ; i ++){ console.log(list[i]()); } //0 1 2 3 4 ``` ``` function fn(){ var arr = []; for(var i = 0;i < 5;i ++){ arr[i] = function(){ return i; } } return arr; } var list = fn(); for(var i = 0,len = list.length;i < len ; i ++){ console.log(list[i]()); } //5 5 5 5 5 ``` ``` var lis = document.getElementsByTagName("li"); for(var i=0;i