javascript作用域和声明提升

javascript看起来像是类C语言的一种,正因为如此其作用域给很多c/c++/java背景的程序员带来一些误解。

考虑下面的例子,想一想程序的输出。

var i =1;
function f(){
if(!i){
var i = 10;
}
alert(i);
}
f();

按照C语言的理解,第一行定义了全局变量i初始化为1,那么var i=10应该执行不到,alert的结果应该是1。但正确的答案是10。

再看下面的一个例子:

var i =1;
function f(){
 i =10;
return;
 var i = 2;
}
f();
alert(i);
按照C语言的理解,应该输出10,但正确的答案是1。


上面的例子看起来的确有点让人难以理解,但这就是javascript的一个语言特性:声明提升(Hoisting)

在了解声明提升之前有必要先对javascript的作用域概念有所了解。

在C语言中,变量作用域是块范围的,在if/for等代码块中可以定义新的变量。

但是javascript中的作用域是函数范围的,只有函数可以创建新的作用域。

下面的例子很好的说明了javascript的作用域:

var i =1;
console.log(i);//1
if(true){
var i = 10;
console.log(i);// 10
}
console.log(i);// 10
if代码段中的i实际上还是全局定义的i,因此它改变了全局变量i的值。

在firebug中最后输出为10。可见这和C语言是完全不同的。


了解了javascript中的作用域的概念后,我们再来看看变量的声明、名字和声明提升。

在javascript中,有4种命名方式:

  1. 语言定义: 缺省情况下,所有的作用域都有thisarguments.
  2. 函数参数: 函数可以有参数,在函数体中起作用
  3. 函数声明: 格式是 functionf(){}
  4. 变量声明: 格式是 var i;
函数和变量声明总是被javascript解释器悄悄提升到作用域的开头。

比如最上面给出的示例1中,变量i虽然定义在了第2行,

但实际上javascript是按照下面的代码来解释的:

var i =1;
function f(){
 var i;
  if(!i){
i =10;
}
alert(i);
}
f();
这样你就能理解为什么第一个示例的输出结果是10了,因为f函数中新创建的局部变量的声明被提升到了函数开头,处于undefined状态。

这样i = 10语句得到了执行并被alert出来。

同样的道理。在示例2中,虽然在return之后定义了局部变量,但实际上由于声明提升,该局部变量仍然被有效声明了。

所以函数内部的处理仅仅改变了局部变量i的值,并未对函数体外面的全局变量i造成任何影响。

你可以试着把return后面的一行定义语句去掉,再执行一次,结果将是10。


最后让我们看看javascript规范ECMAScript Standard)中是怎么说的:

If the variable statement occurs inside a FunctionDeclaration, the variables are defined with function-local scope in that function, as described in section 10.1.3. Otherwise, they are defined with global scope (that is, they are created as members of the global object, as described in section 10.1.3) using property attributes { DontDelete }. Variables are created when the execution scope is entered. A Block does not define a new execution scope. Only Program and FunctionDeclaration produce a new scope. Variables are initialised to undefined when created. A variable with an Initialiser is assigned the value of its AssignmentExpression when the VariableStatement is executed, not when the variable is created.


完。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值