Js作用域链及变量作用域【详解】

要理解变量的作用域范围就得先理解作用域链 :
用var关键字声明一个变量时,就是为该变量所在的对象添加了一个属性。    
作用域链由于js的变量都是对象的属性,而该对象可能又是其它对象的属性,而所有的对象都是window对象的属性,所以这些对象的关系可以看作是一条链    
链头就是变量所处的对象,链尾就是window对象。

看下面的代码:

function t() { 
var a; 
function t2() { 
var b; 
} 
}

js中函数也是对象,所以变量a所在的对象是t,t又在window对象中,所以a的作用域链如下
t--window    
那么b所以在的对象即t2,t2又包含在t中,t又在window对象,所以b的作用域链如下    
t2--t--window    
明白了作用域链下面就开始变量的作用域分析了    
      
1 javascript 没有var的变量都为全局变量,且为window对象的属性

复制代码
function test1() { 
//执行这个句的时候它会找作用域对象,这个函数就是作用域链中的第一个对象,但这个对象中没有相关的var语句 
//于里就找作用域链的第二个对象,即全局对象,而全局对象中也没有相关的var语句 
//由于没有相关的var语句,js隐式在函数地声明了变量即var all; 
all = 30; 
alert(all); 
} 

test1();

alert(all); 
alert(window.all);
复制代码

2 函数内(函数内的函数除外)定义的变量在整个函数内部都有效

复制代码
function test2() { 
var t = 0; 
//在for的条件里定义变量,这个变更的作用域链对象是这个函数 
//因此在整个的函数里它是有效的 
for (var i = 0; i < 5; i++) { 
t += i; 
} 
alert(i); 
} 
test2();
复制代码

3 函数内部的变量取代全局同名变量

复制代码
var t = "bb"; 
function test() { 
//执行t的时候,它会先找作用域链对象,由于它定义在函数内部,所以这个函数就是它的作用域链的第一个对象 
//而在这个对象里又有t的定义,所以t就是局部变量了,它替换了全局变量t

//t只是此时有定义,但并没有赋值,赋值在下一行,所以这里输出了undefined 
alert(t); 
var t = "aa"; 
alert(t); 
} 
test();
复制代码

4 没块的作用域

if (true) { 
//在块中定义了一个变量,它的作用域链的第一个对象就是全局对象window 
var tmp = 0; 
} 
//tmp的作用域链的第一个对象就是全局对象window,而上面又有全局对象中相关的var语句,因此输出0 
alert(tmp); 

对于js编译器对变量做了一些什么事情,参加下面博文

只要是写过点JS代码,很简单一个var 就完事了。那对于JS编译器背后它又发生了什么呢?那就一步步通过代码来讲起,需要了解的朋友研究一下。

只要是写过点JS代码,很简单一个var 就完事了。那对于JS编译器背后它又发生了什么呢?那就一步步通过代码来讲起。
复制代码 代码如下:
x = 1;
alert(x);
var y = function() {
alert(x);
var x = 2;
alert(x);
}
y();

上面的代码也会你答对了它会分别输出:1,undefined,2。对于我来说,第一反应它会输出:1,1,2。为什么第二个会输出undefined?在上面我明确定义了一个全局变量x,为何找不到?

那是因为:js编译器在执行这个y函数的时候,会把把它body里面的声明变量提前到最前面进行声明。比如:var x=2; 编译器先会在body最前面进行var x 声明。其实上面的代码等同于下面的这段代码:
复制代码 代码如下:
x = 1;
alert(x);
var y = function() {<BR>var x;//此时x还未赋值,所以为undefined。
alert(x);
x = 2;
alert(x);
}
y();

所以也就不难理解x=undefined的了.但是如果把var x = 2;这段代码给删掉,在内部它没有进行var声明。它会一直沿着作用域向上找,此时的x 就为全局x.
接下来再看一个更有趣的例子。
复制代码 代码如下:
var a = 1;
function b() {
a = 10;
return;
}
b();
alert(a);
///
var a = 1;
function b() {
a = 10;
return;
function a() {}
} b(); alert(a);

例子很简单。第一个例子为输出10,第二个会输出1。这是为什么呢?况且第二个例子我都return 了。按理都应当输出10才对呀!那时因为JS编译器在背后作怪。
两段代码差别就是第二个例子多了个function a(){};便这个函数体里面什么也没有,并且也没有对它进行任何调用。

其实JS编译器在背后会把function a() {}编译成 var a=function (){}。此时对于函数内部也有一个a=10; 外面的a些也还是1;根据JS作用域。会先找内部的a,如果找不到再向上一级一级找。
最张alert(a) 就会显示1;

以上内容参考:http://www.cnblogs.com/mu-mu/archive/2012/11/19/2777007.html

和:http://www.jb51.net/article/32889.htm

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值