1.2.3中有一段话
函数声明只能作用于全局中,或者镶嵌在其他函数中。不能出现在循环,条件中(待确认)
循环判断中的声明函数不存在变量提升到花括号外,只提升在花括号内。变量声明存在,作用域还为js作用域(函数作用域与全局作用域)。
console.log(foo) // 找不到,声明函数提升是整个内容提升 console.log(a) // 找不到 存在提升 if (1) { console.log(foo) // 找到了 说明提升了 但是只在循环中 console.log(a) function foo() {} var a = "1" } VM1374:1 undefined VM1374:2 undefined VM1374:4 ƒ foo() {} VM1374:5 undefined console.log(foo) console.log(a) for (var i = 0; i < 2; i++) { console.log(foo) console.log(a) function foo() {} var a = "1" } VM1446:1 undefined VM1446:2 undefined VM1446:4 ƒ foo() {} VM1446:5 undefined VM1446:4 ƒ foo() {} VM1446:5 1
我们还是先上例子
function createFunctions(){ var result = new Array(); for(var i=0; i<10; i++){ result[i] = function(){ console.log(i) //此处若没有打印出,就说明i没有进入到函数中 return i; } } return result }
createFunctions() //发现返回的一个包含十个函数的数组 (10) [ƒ, ƒ, ƒ, ƒ, ƒ, ƒ, ƒ, ƒ, ƒ, ƒ]
createFunctions()[0]。//看看是包含的什么函数 ƒ (){ console.log(i) //此处若没有打印出,就说明i没有进入到函数中 return i; } function createFunctions(){ var result = new Array(); for(var i=0; i<10; i++){ result[i] = function(){ console.log(i) //此处若没有打印出,就说明i没有进入到函数中 return i; }() //增加了立即执行。把函数变成了一个值 } return result } createFunctions() //返回了一个包含数字的数组 VM1196:5 0 VM1196:5 1 VM1196:5 2 VM1196:5 3 VM1196:5 4 VM1196:5 5 VM1196:5 6 VM1196:5 7 VM1196:5 8 VM1196:5 9 (10) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
- 循环中不适合用声明函数,因为一般循环外调用,是循环结束的时间,只能拿到任何变量中的最后一个值
- 由此可见第一个解决方案为函数在循环中使用立即执行函数调用
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
闭包只能取得包含函数中任何变量的最后一个值
- 作用域链的这种机制,注定了循环中定义函数会有这种副作用
- 所以在函数应用时候,循环早已经停止,当前i值为4. 所以undefined
重点 es6中有了新的变量声明let 就可以完全解决因为作用域链的机制。let为块状作用域,其作用区域只在花括号内
【解决原因需要再研究】
例子1解决方案2 function createFunctions(){ var result = new Array(); for(let i=0; i<10; i++){ result[i] = function(){ return i; } } let vvv = result[0]() return vvv } createFunctions() 0 例子2解决方案2 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[3](); console.log(result); VM2197:11 d
- 上述例子2解决方案2。是否因为立即执行函数的函数