关于闭包
词法作用域(lexical environment)
作用域链
- 函数在执行的过程中,先从自己内部找变量
- 如果找不到,再从创造当前函数所在的作用域(词法作用域)去找,以此往上
- 注意找的是变量的当前状态
函数连同它作用域链上的要找的这个变量,共同构成闭包
一般情况下使用闭包住要是为了
- 封装数据
- 暂存数据
例子
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 
 | var fnArr = [];for (var i = 0; i < 2; i++){
 fnArr[i] = (function(j){
 return function(){
 return j
 }
 })(i)
 }
 
 fnArr[1]()
 
 | 
这个例子里有两个闭包,
相当于可以将for循环拆开,等效于以下代码
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 
 | fnArr[0] = (function(j){return function(){
 return j;
 }
 })(0)
 
 fnArr[1] = (function(j){
 return function(){
 return j;
 }
 })(1)
 
 
 fnArr[1]();
 
 | 
再简化一下,写成a,b 函数
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 
 | var a = (function(j){return function(){
 return j;
 }
 })(0)
 
 var b = (function(j){
 return function(){
 return j;
 }
 })(1)
 
 b();
 
 | 
再同步一下,将var b里的立即执行函数单独拆出来,
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 
 | var a = (function(j){return function(){
 return j;
 }
 })(0)
 
 function fn2(j){
 var j = arguments[0];
 return function(){
 return j;
 }
 }
 
 var b = fn2(1);
 
 b();
 
 | 
其他的等效方法
方法1:
| 12
 3
 4
 5
 6
 7
 
 | var fnArr = [];
 for(var i = 0; i < 2; i++){
 fnArr[i] = (function(j){
 return j;
 })(i)
 }
 
 | 
方法2:
| 12
 3
 4
 5
 6
 7
 8
 
 | var fnArr = [];for(var i = 0;i < 2; i++){
 (function(i){
 fnArr[i] = function(){
 return i;
 }
 })(i)
 }
 
 | 
方法3:(使用ES6)
| 12
 3
 4
 5
 6
 
 | var fnArr = [];for(let i = 0; i < 10; i++){
 fnArr[i] = function(){
 return i;
 }
 }
 
 | 
闭包例题
封装一个Car对象
可以将其封装成一个对象返回,由于形成闭包,当调用方法时,不会对原有的参数speed进行影响。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 
 | var Car = (function(){var speed = 0;
 
 function setSpeed (s) {
 speed = s;
 }
 
 function getSpeed (){
 return speed
 }
 
 function speedUp(){
 speed++
 }
 
 function speedDown(){
 speed --;
 }
 
 return {
 setSpeed: setSpeed,
 getSpeed: getSpeed,
 speedUp: speedUp,
 speedDown: speedDown
 }
 })()
 
 |