原文请访问http://www.cnblogs.com/rubylouvre/archive/2009/08/21/1551270.html,
我也只是为了做个记录
javascript变量的作用域
<script type="text/javascript">
var a=100;
var b=true;
function test(){
alert(a);
alert(b);
b=false;
alert(b);
var a=200;
alert(a/2);
alert(++Math.PI);
alert(Math.PI++);
}
test();
</script>
为什么第一个alert为undefined,而第二个为true。这问题也可以延伸为——alert(b)时怎么就会找外部的b,而alert(a)时就不会往外面找?!
我们都明白局部变量的优先级大于全局变量,或者说内围作用域的变量的优先级比外围的高。当JS引擎在当前作用域找不到此变量时,它就往外围的作用域找。不过, 在这之前,有一个严肃的问题是,究竟当前作用域存不存在这个变量。像javascript这样的解释型语言,基本分为两个阶段,编译期(下面为符合大多数语言的称呼习惯,改叫预编译)与运行期。在预编译阶段,它是用函数来划分作用域,然后逐层为其以 var 声明的变量(下略称为var变量)与函数定义开辟内存空间,再然后对var变量进行特殊处理,统统赋初始值为undefined,如下图:
由上图,我们便可以推知,当前网页拥有两个a,一个b,一个test函数。如果在运行期用到除此以外的东东,如c函数或d变量啦,就会报未定义错误(用eval等非正常手段生成变量与函数的情况除外),此外,它们最多出现未赋值警告。
javascript的运行期是在为var变量与函数定义分配空间后立即执行,并且是逐行往下执行的。
- 第1行它为外围作用域的a赋值为100
- 第2行它为外围作用域的b赋值为true
- 第3行进行test的作用域,我们简称为内围作用域。
- 第4行就立即调用内围作用域的a,这时它还没有来得及赋值呢!不过它已经声明过了,因此默认为其赋值为undefined(在预编译阶段,见图),于是alert为undefined
- 第5行就调用b时,JS引擎就拿起我画的图看了(笑),发现test的作用域内没有b,眼睛往外望,发现b了,而b在第二行就赋值为true,于是alert为true。
- 第6行为一个赋值操作,把外围的b变量改赋为false。于是到第7行时,alert为false。以下说法不说了。
作为对比,我们改写一下例子:
这时在test函数的作用域内,b也被声明了。
掌握预编译为var变量与函数定义分配空间这一事实后,许多问题就迎刃而解。我们看犀牛书上的一个例子。
var scope = "global" ; |
function f() { |
alert(scope); |
var scope = "local" ; |
alert(scope); |
} |
f(); |
答案呼之欲出!
我们来看更复杂的例子。
Object.prototype.test = ‘wrong‘ ; |
var test = ‘right‘ ; |
( function f() { |
alert(test); |
})(); |