作用域
js看似有”块级作用域“其实它没有,取而代之的是“函数作用域”。
块级作用域:
在一个代码块(一对花括号内)定义的变量在代码块外部是不可见的,且在代码块执行结束后被释放掉。
函数作用域:
定义在该函数中的参数和变量在函数外部不可见(例子1),而一个函数内部任何位置定义的变量,在该函数内部任何地方都可见(例子2)。
解释二:也就是说,变量不仅在声明它们的函数体内有定义,还在这个函数体嵌套的任意函数体内都有定义。(例子1里的d)
例子1
var foo=function(){
var a=3,b=5,d=2;
var bar=function(){
var b=7,c=11;
document.writeln('1.bar内的a='+a+'b='+b+'c='+c+'d='+d+'<br>');
a=b+c;
document.writeln('2.bar内的a='+a+'b='+b+'c='+c+'<br>');
};
document.writeln('3.foo内的a='+a+'b='+b+'<br>');//c无定义
bar();
document.writeln('4.foo内的a='+a+'b='+b+'<br>');//c无定义
}
foo();
//运行结果
3.foo内的a=3 b=5
1.bar内的a=3 b=7 c=11 d=2
2.bar内的a=21 b=7 c=11
4.foo内的a=21 b=5
例子2:
var o={};
function test(o){
var i=0; //i在整个函数体内有定义
if(typeof o=="object"){
var j=1; //j在函数体内有定义,不仅是在这个代码块内
for(var k=0;k<2;k++){ //k在函数体内有定义,不仅仅是在这个循环体内
console.log(k); //输出数字0-1
}
console.log(k); //k已经定义了,输出2
}
console.log(j); //j已经定义了,且已初始化为1
console.log("我是循环里的k="+k); //我是循环里的k=2
}
声明提前
变量在声明之前就已经可用。
例子:
var scope="global";
function f(){
console.log(scope);// 输出undefined而不是global
var scope="local"; //变量在这里被赋值 ,但是变量本身在函数体任何地方都有定义
console.log(scope);//输出 local
}
也就是:将变量的声明“提前”到函数顶部,同时变量初始化留在原来的位置。
function f(){
var scope;
console.log(scope);
var scope="local";
console.log(scope);//输出 local
作用域链
遍历嵌套作用域链的规则很简单:引擎从当前的执行作用域开始查找变量,如果找不到, 就向上一级继续查找。当抵达最外层的全局作用域时,无论找到还是没找到,查找过程都 会停止。