js变量的声明和作用域关系


每个语言的变量的声明方式各有不同,变量也有其作用域。比如php也有全局变量,需要用超级全局变量$GLOBALS或者global声明来实现。

$GLOBALS['var']是外部的全局变量本身,global $var是外部$var的同名引用或者指针。


从笔试题开始

来看几道js笔试题吧。

笔试题以及题目分析内容(题一,题二)来自:浅谈 js 变量作用域

题一:

var a, b = 0, fn = function(){ var a = b = 2; };
fn();
console.log(a, b);

看上去很简单的一道题,细细分析一下却发现这题出的真妙。咱们一行一行分析

第一行声明了a,b,fn,此时a声明但未赋值,故a=undefined,b=0,fn为一个函数。

第四行执行fn函数。

在fn函数内部 var a=b=2; 这里才是真正的重点,var a重新使用 var 对 a做了覆盖声明,并把 b 的值赋给它。后面 b =2。这里 b 并没有使用 var 声明。事实上这一行是创建了一个函数内部的变量 a,和对全局变量 b 进行赋值。所以虽然这里 a 也被赋值了,但此时它是个函数内部的变量,外部无法访问

第五行,输出全局变量a和b,所以此时a=undefined,b=2;


换一种写法,题二:

var a, b = 0, fn = function(){
    var b=1;
    a = b = 2;
    console.log(a, b);
};
fn();
console.log(a, b);

和上面一样,第一行对三个变量声明。

此时第四行输出a和b时都是函数内部的变量,a和b都是2。

最后一行输出的时候全局变量a是,在函数内部被赋值,所以是2。全局变量b在第一行被赋值0,但是在函数内部第三行被var 重新声明为函数内部的变量,虽然被赋值为1,虽然下一行被赋值为2,但是事实上和全部变量b是没有关系的。所以此时b为0


再来,题三:

var a, b = 0, fn = function(){
    var b=1;
    a = b = 2;
    c=3
    console.log(a, b,c);//2 2 3
};
fn();
console.log(a, b,c);//2 0 3

与题二不同的就是加了变量c,变量c即未在全局声明,也未在函数内容使用var声明,但是在最后一行的输出中,确实实打实的输出了3。

那是因为,当在函数内部使用未声明的变量时,且往外层找不到该变量的声明,那么就会在函数内部声明这个变量为全局变量。


再来一题

var scope="global";  
function t(){  
    console.log(scope);  //undefined
    var scope="local"  
    console.log(scope);  //local
}  
t(); 

一脸懵逼了,第一个输出居然不是global。js真心奇葩。不过也没人闲的蛋疼写这种代码了。。


总结

与php不同的是,js在函数中使用的变量,如果未使用var重新声明的话,则会向上寻找该变量,直到找到该变量被声明之处为止。

就像上面的题目1中,在函数内部的b变量未做声明,则向上寻找至第一行全局变量的声明var b,找不到就出现题三中变量c的情况了。

如果在函数内容声明的话,则其作用域只在该函数内部了。


javascript


上一篇:YPHP后台中RBAC实现整理(节点篇)

微信小程序POST请求无法带上参数:下一篇