`

变量提升

 
阅读更多

看一个有趣的例子,它显示了关于局部和全局作用域的一个重要问题:

 

    var a =123;
    function f() {
        console.log(a);
        var a = 1;
        console.log(a);
    }
    f();

        您可能会想当然的认为console.log()第一次显示123(也就是全局变量a的值),第二次显示1(即局部变量a)。但事实并非完全如此,查看firebug输出结果,如下:

> undefined
> 1
 

      这是因为函数域始终优于全局域,所以局部变量a会覆盖掉所有与它同名的全局变量,尽管在console.log()第一次被调用时,a还没有被正式定义(即该值为undefined),但该变量本身已经存在于本地空间了。这种特殊现象叫做提升(hoisting)。

    也就是说,当Javascript执行过程进入新的函数时,这个函数内部声明的所有变量都会被移动(或者说提升)到函数最开始的地方。这个概念很重要,必须牢记。另外需要注意的是,被提升的只有变量声明,这意味着,只有函数体内声明的这些变量在该函数执行开始时就存在,而与之相关的赋值操作并不会被提升,它还在原来的位置上。上述例子可以被等价的写为:

 

    var a =123;
    function f() {
        var a; // some as: var a= undefined;
        console.log(a); // undefiend;
        var a = 1;
        console.log(a); // 1
    }

 

     再看一个有趣的例子:

    console.log('global1:'  + window.a);
    function hehe()  {
        console.log('func area1:' + window.a);
        console.log('func area2:' + a);
    }
    hehe();
    console.log('global2:'  + window.a);

 您可能认为输出结果是这样的:

> global1: undefined
> func area1: undefined
> func area2: undefiend
> global2: undefined
 

通过查看firebug控制台,实际结果是这样的:

> global1:undefined
> func area1:undefined
> ReferenceError: a is not defined

 

    在输出func area1的时候出错了。为什么func area1 和func area2不同呢,a不应该是全局变量吗?如果因为未定义而出错,那window.a为啥不出错?

    原来,在javascript里,如果访问的对象的属性不存在,代码就会返回undefiend,window.a属于不存在的属性,所以返回undefined,而a属于不存在的变量,故出错,二者性质不通,把window.a改成其他对象效果是一样的:

    var o = {};
    console.log(o.v);

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics