案例一:
1 var x=100; 2 alert(x); 3 //等同于 4 window.x=100; 5 window.alert(x);
理解:定义的全局变量都是window对象的属性,而一些像alert()这样的默认方法为window对象下的方法。
案例二:
1 alert(x);//弹出undefined 2 var x="yewenxiang"; 3 4 function test(){ 5 alert(x); 6 var x="yewenxiang"; 7 } 8 test();//弹出undefined
等价于:
1 var x; 2 alert(x);//弹出undefined 3 x="yewenxiang"; 4 5 function test(){ 6 var x; 7 alert(x); 8 x="yewenxiang"; 9 } 10 test()//弹出undefined
理解:Javascript引擎会先扫描整个函数,把所有变量的声明提升到函数体顶部,在函数外面也是会先把全局变量的申明提升到顶部,这个叫变量的提升。
案例三:
1 alert(typeof test); 2 var test=function (){}; 3 //弹出undefined; 4 //等价于 5 var test 6 alert(typeof test); 7 var test=function (){};
alert(typeof test); function test(){}; //弹出function; 等价于 function test(){}; alert(typeof test);
理解:函数也会像变量一样被提升,不同的是对于函数声明和定义同时提到前面,而变量只是把声明提到了前面,定义没有提前。
案例四:
1 var x="yewenxiang"; 2 function test(){ 3 var y="xiangwang"; 4 function test2(){ 5 var z="tiandongxue"; 6 function test3(){ 7 alert(x); 8 } 9 test3(); 10 } 11 test2(); 12 } 13 test();//弹出yewenxiang;
理解:函数首先在test3()中查找是否定义了变量x,没有,去上一层test2中查找,没有,再去test1中去找,继续没有,跑函数外面找去了,OK终于找到了var x="yewenxiang",函数内查找变量属于就近原则.
1 var x="yewenxiang"; 2 function test(){ 3 var y="xiangwang"; 4 var x; 5 function test2(){ 6 var z="tiandongxue"; 7 function test3(){ 8 alert(x); 9 } 10 test3(); 11 } 12 test2(); 13 } 14 test();//弹出undefined
理解:Javascript也喜欢偷懒,我既然可以在内部找到var x,何必跑出去找var x="yewenxiang".符合函数内局部变量的优先级比全局变量高。
案例五:
function test(){ var x="yewenxiang"; } test(); alert(x);//x is not defined //因为在函数内部定义var为局部变量,只能在函数内部使用。 function test(){ x="yewenxiang"; } test(); alert(x); //弹出yewenxiang ,不加var,相当于定义了一个全局变量,没调用函数时报错x is not defined, //调用函数后弹出yewenxiang(注意严格模式下调用函数也会报错x is not defined)。 function test(){ x="yewenxiang"; } alert(x); test(); //报错x is not defined 个人理解只要弹出前没调用函数都报错。 var x="xiangwang" function test(){ x="yewenxiang"; } test(); alert(x); //弹出yewenxiang 函数内部的全局变量覆盖了外面定义的var x="xiangwang", //这种情况下严格模式也没报错,因为函数外面定义了全局变量x。
案例六:
function test(){ var i=1; if(i){ var j=0; for(var k=0;k<3;k++){ alert(k);//0,1,2 } alert(k);//3 } alert(j);//j } test(); //i j k 作用域是相同的,在函数test内是全局的,都可被访问。 function test(){ let i=1; if(i){ let j=0; for(lef k=0;k<3;k++){ alert(k); alert(i); } alert(k); } alert(j); } test();//按顺序弹出0-1-1-1-2-1-报错k is not defined-报错j is not defined
理解:let为ES6新增的,解决ES5之前没有块级作用域的问题,这两段段代码说明:函数中的for if while等中定义的var变量,在函数中属于全局变量,都可以被访问。而定义为let,只能在内层去往外层访问定义的let变量,外层访问不了内层定义的let变量.
碰到的坑1:
1 function test(){ 2 name="yewenxiang"; 3 } 4 alert(name); 5 //弹出一个空的对话框。 6 ------------------------------ 7 function test(){ 8 name="yewenxiang"; 9 } 10 test(); 11 alert(name);//弹出yewenxiang 12 //然后删除test() 刷新页面还是弹出yewenxiang ,然后关闭页面重新加载测试页面弹出空的对话框
执行的结果跟我预料的不一样,我认为的是第一段代码应该报错name为未定义,第二段删除test()后也应该会报错,但是修改代码后刷新页面还是弹出yewenxiang,然后关闭页面重新加载测试页面弹出空的对话框这种诡异的事情,最后发现问题所在:因为name属于Javascript 内置的对象、属性和方法的名称,应该避免使用保留字,换成x后正常。
目前未解决坑2:
1 function test(){ 2 alert(x); 3 x="yewenxiang"; 4 } 5 test(); 6 //报错x is not defined, 如果加var 则变量会提升弹出undefined,不加var 变量为什么没有提升而是直接报错。
以上是我对于变量作用域的一些理解和总结,包括未解决的问题,理解中有错误还希望能指出。