有过类似C语言编程经验的同学应该都知道“块级作用域(block scope)”:花括号内的每一段代码都具有各自的作用域,而且在声明它们的代码段之外是不可见的。而在JavaScript中是没有块级作用域的,JavaScript取而代之地使用了“函数作用域(function scope)”:变量在声明它们的函数体以及这个函数体嵌套的任意函数体内都是有定义的。
光用文字解释平白无味,先来段让你为之一振的代码:
function myTest(num){ var i = 0; if(num == 222){ var j = 0; for(var k=0; k<2; k++){ console.log(k); } console.log(k); } console.log(i); console.log(j); console.log(k); console.log(m); } myTest(111);
请认真阅读代码,仔细思考,认真回答问题。下面给出浏览器中运行的结果,检验下自己的答案吧!
如果你完全回答正确,并且已经明白所有原因,那么就没必要看下去了;如果你还未明白原因并且有一颗好奇、意欲一探究竟的心,那么就下来就要认真看完本博客了。
既然不懂,那就再继续认真看解释呗:JavaScript的函数作用域是指在函数内声明的所有变量在函数体内始终是可见的,这就意味着变量在声明之前甚至已经可用了。JavaScript这个特性被非正式地称为声明提前,即JavaScript函数里声明的所有变量(但不涉及赋值)都被提前至函数体的顶部了。这么说上面的例子中代码就等同于
function myTest(num){ var i,j,k; i = 0; if(num === 222){ j = 0; for(k=0; k<2; k++){ console.log(k); } console.log(k); } console.log(i); console.log(j); console.log(k); console.log(m); }
所以即使代码运行时没有进入if条件语句中,但变量i,j,k已经声明了(即使是在for循环中声明的k声明也提前了呢),只是i初始化为0,而j,k没有初始化而已,所以j,k输出是undefined。至于m,因为它根本就没有声明过,所以调用时就报错了。现在明白了吧,下面再来一题自己检测下掌握情况吧:
var str1= "out1"; var str2 = "out2"; function myTest(){ console.log(str1); console.log(str2); var str2 = "inner"; console.log(str2); }myTest();
结果是什么呢?下面给出浏览器的回答,检验一下你心中的答案吧!
给JS学习者一个建议:尽量将变量声明放在函数体顶部,而不是将声明放在使用变量之处,这种做法会使代码清晰地反映了真实的变量的作用域。
下面是在下衷心送给各位看官的五个欢迎(O(∩_∩)O~):欢迎转载、欢迎收藏、欢迎评论、欢迎点赞、欢迎推荐!