JavaScript在循环中定义函数的问题

    最近在工作中遇到一个让人头疼的问题,需要定义21个函数,函数的主体是一样的,功能也是一致的,仅仅是返回值不同。基本的结构是这样的

var arr = ["a","b","c","d"];
var funcArr = [];
for (var i = 0; i < 4; i++) {
	funcArr[i] = function(){
		return arr[i];
	}
}
var result = funcArr[0]();
console.log(result);    //undefined

    表面上看,每个函数都应该基于自己在数组中的位置返回不同的值,但是实际上,每次返回的都是undefined。这是为什么呢?

    纠结了很久没解决掉。过了大概一个月的时间,在《js高程》上看到了一个相似的例子。

function createFunctions(){
	var result = new Array();
	for(var i=0; i<10; i++){
		result[i] = function(){
			return i;
		}
	}
	return return
}

    这个函数返回一个函数数组。还有一点点闭包的意味,但是这不是重点,重点是书上这就话“闭包只能取得包含函数中任何变量的最后一个值”。作用链的这种机制,注定了在循环中定义函数会产生这种副作用。虽然在实际中我并没有用到闭包,但是原理是一样的,都是作用域联的问题。当createFunctions()函数返回时,i的值为10,此时每个函数都引用着保存变量i的同一个变量对象,所以每个函数内部i的值都是10。

    换做我遇到的问题。函数在应用时,循环早已停止,当前的i值是4,函数返回值是arr[4],就是undefined。

    解决方案是创建另一个匿名函数强制让闭包行为符合预期。应用到我的例子就是这样:

var arr = ["a","b","c","d"];
var funcArr = [];
for (var i = 0; i < 4; i++) {
	funcArr[i] = function(num){
		return function(){
			return arr[num];
		};
	}(i)
}
var result = funcArr[0]();
console.log(result);    //"a"

    立即执行函数保证了每个函数中的i是当时循环到的i值,即使循环结束,i值在循环中已经以副本num的形式确定下来了。

//2018-03-29******

    可以使用ES6的新的声明变量的方法解决这个问题,简单优雅,看代码:

var arr = ["a","b","c","d"];
var funcArr = [];
//使用let代替var
for (let i = 0; i < 4; i++) {
	funcArr[i] = function(){
		return arr[i];
	}
}
var result = funcArr[0]();
console.log(result);    //"a"
    let声明的变量是块级作用域的。循环中不会共享一个i值。

猜你喜欢

转载自blog.csdn.net/zhangxuekang/article/details/79531720
今日推荐