js闭包 (多图,移动端慎点)

最近在看js的闭包,有一个地方看了许久都没有理解。

1     function createFunctions() {
2         var result = new Array();
3         for (var i = 0; i < 10; i++) {
4             result[i] = function () {
5                 return i;
6             }
7         }
8         return result;
9     }

书上说每个函数都返回10,我百思不得其解,总觉得返回的应该是0,1,2,3....9。于是自己写代码测试了一下,果然是都是10. 

1     var getResult = createFunctions();
2     console.log(getResult);
3     for (var i = 0; i < 10; i++) {
4         var tt = getResult[i];
5         console.log(tt());
6     }

当时第一次写的时候console.log()里的tt是没有加圆括号的,结果拿到的是十个一模一样的函数。技术分享

每个函数体都是return i;这时我忽然明白了,在createFunctions函数内部只是为每个数组元素赋值为具有相同函数体的匿名函数,而并没有执行这个函数。真正想要获得这些函数值是需要执行函数的。而当执行这些函数时,createFunctions的作用于链已经被销毁了,只留下了i这个活动对象被保存在匿名函数的作用域链中,而此时i的值为10.因此10个函数的执行结果均为10.

 

那么要想数组中的元素分别是那些索引应该怎么办呢?此时我在createFunctions的函数内部直接把匿名函数执行后的结果赋值给了数组中的元素,代码如下:

 1     function createMyFunctions() {
 2         var result = new Array();
 3         for (var i = 0; i < 10; i++) {
 4             result[i] = (function () {
 5                 return i;
 6             })();
 7         }
 8         return result;
 9     }
10     var getMyResult = createMyFunctions();
11     console.log(getMyResult);

 

但是这样的话,getMyResult数组中的元素就是[0,1,2,...,9]了。那如果想让数组中的元素仍然为十个函数,但是函数的返回值是索引,书上是这样写的:

 1     function createTheirFunctions() {
 2         var result = new Array();
 3         for (var i = 0; i < 10; i++) {
 4             result[i] = (function (num) {
 5                 return function () {
 6                     return num;
 7                 };
 8             })(i);
 9         }
10         return result;
11     }
12     var getTheirResult = createTheirFunctions();
13     console.log(getTheirResult);
14     for (var i = 0; i < 10; i++) {
15         var tt = getTheirResult[i];
16         console.log(tt());
17     }

上面是利用了嵌套函数,还有另一种方法是使用with语句创建块级作用域:

 1     function createYourFunctions() {
 2         var result = new Array();
 3         for (var i = 0; i < 10; i++) {
 4             var t = {value: i};
 5             with (t) {
 6                 result[i] = function () {
 7                     return value;
 8                 };
 9             }
10         }
11         return result;
12     }
13     var getYourResult = createYourFunctions();
14     console.log(getYourResult);
15     for (var i = 0; i < 10; i++) {
16         var tt = getYourResult[i];
17         console.log(tt());
18     }

 当然用with并不是我想出来的办法,是一位大神想出来的,听了大神一大堆的分析后,我深感js的深奥!

下面附上和大神的聊天记录(研究如何输出0-9):

技术分享技术分享技术分享

 

技术分享技术分享

 

技术分享技术分享技术分享

技术分享

 

技术分享

 

技术分享技术分享

 

技术分享技术分享

技术分享

 

技术分享

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。