每个语言的变量的声明方式各有不同,变量也有其作用域。比如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的情况了。
如果在函数内容声明的话,则其作用域只在该函数内部了。