V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a JavaScript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
JavaScript 权威指南第 5 版
Closure: The Definitive Guide
aaronlam
V2EX  ›  JavaScript

JavaScript Hoisting 的问题

  •  
  •   aaronlam · 2015-04-09 11:28:22 +08:00 · 2551 次点击
    这是一个创建于 3305 天前的主题,其中的信息可能已经有所发展或是发生改变。

    最近在学习 JavaScript 然后刚好碰到这个神奇的问题,百思不得其解:

    var a = 1;

    function foo() {
    if (!a) {
    var a = 2;
    }
    alert(a);
    };

    foo();

    结果:2

    上面的 function foo() 中的 alert 弹出了 2 ,应该是说明了 if 里的 var a 被提升了。但是提升不是只提升 变量的声明 吗?想问为什么 a 被成功赋值为 2 了?(ಠ .̫.̫ ಠ)

    然后我尝试把 if 的条件改为了 false 后:

    var a = 1;

    function foo() {
    if (false) {
    var a = 2;
    }
    alert(a);
    };

    foo();

    结果:undefined

    说好的提升呢?(☍﹏⁰) 不提升好歹也弹出全局变量的 1 把?为什么是 undefined????(♩¬3¬)

    真心求指教,被这个提升搞到头都大了。

    第 1 条附言  ·  2015-04-09 12:23:41 +08:00
    感谢各位的回答!!!!现在整个人豁然开朗了。
    那我就以我已经了解的来解释一下我自己所提问的问题吧。

    源代码:
    var a = 1;

    function foo() {
    if (!a) {
    var a = 2;
    }
    alert(a);
    };

    foo();

    解释器解释后:
    function foo() {
    var a;
    if (!a) {
    a = 2;
    }
    alert(a);
    };

    var a = 1;

    foo();

    解释器解释后详解:
    1、 [函数声明优于变量声明,所以被提升与 var a = 1; 上面]
    function foo() {
    2、 [因为函数里的 if 里有 var = a 变量声明,故被提升至函数作用域的顶部]
    var a;
    3、 [此时被提升的 var a 相当于 var a = void(); 所以 a = false 则 !a = true]
    if (!a) {
    4、 [所以 a =2 就被成功的赋值了]
    a = 2;
    }
    alert(a);
    };

    var a = 1;

    foo();
    第 2 条附言  ·  2015-04-09 12:27:20 +08:00
    1、 [函数声明优于变量声明,所以被提升与 var a = 1; 上面] -> 1、 [函数声明优于变量声明,所以被提升至全局 var a = 1; 上面]
    第 3 条附言  ·  2015-04-09 12:46:11 +08:00
    3、 [此时被提升的 var a 相当于 var a = void(); 所以 a = false 则 !a = true] -> 3、 [此时被提升的 var a 相当于 var a = void 0; 所以 a = false 则 !a = true]
    12 条回复    2015-04-09 17:49:24 +08:00
    luin
        1
    luin  
       2015-04-09 11:31:25 +08:00   ❤️ 1
    第一段代码相当于:
    var a = 1;

    function foo() {
    var a;
    if (!a) {
    a = 2;
    }
    alert(a);
    };

    foo();

    更进一步:

    var a = 1;

    function foo() {
    var a = void 0;
    if (!a) {
    a = 2;
    }
    alert(a);
    };

    foo();
    aaronlam
        2
    aaronlam  
    OP
       2015-04-09 11:34:32 +08:00
    @luin 感谢回答!!!!
    我知道 if 里的 var a 会被提升。但是为什么 a = 2 也被成功的执行了呢?
    ChiangDi
        3
    ChiangDi  
       2015-04-09 11:35:26 +08:00 via Android   ❤️ 1
    if 是不会被提升的吧!第一个之所以输出2是因为
    函数被提到最上面了,那时候 a 还没定义,所以 if(!a)为真,执行了 a =2。我是这么想的。
    luin
        4
    luin  
       2015-04-09 11:36:23 +08:00   ❤️ 1
    因为 if (!a) 这个条件是真值(a 的值是 void 0,因此 a 是假值,!a是真值),所以会执行 a = 2。
    ChiangDi
        5
    ChiangDi  
       2015-04-09 11:36:53 +08:00 via Android
    好像不太对。
    ChiangDi
        6
    ChiangDi  
       2015-04-09 11:38:23 +08:00 via Android
    @luin 的回答是正解。
    RoshanWu
        7
    RoshanWu  
       2015-04-09 11:41:02 +08:00   ❤️ 1
    `function` 先于 `var a = 1` 被解析哟。前者内部在解析的时候,a = window.a = undefined, 后者是个干扰,额呵呵~
    想更加深入地了解,请看: http://roshanca.com/2012/traps-in-javascript-part-I/

    话说这个系列写于两年前一直是 part I,这两天一定要逼自己更新了啊啊啊!
    aaronlam
        8
    aaronlam  
    OP
       2015-04-09 11:43:01 +08:00
    @ChiangDi 感谢,但是按照你这么说,解释器解释后是这样

    function foo() {
    if (!a) {
    var a = 2;
    }
    alert(a);
    };

    var a = 1;

    foo();

    全局的 var a = 1; 应该还是会被 声明 并 定义。
    看了下 4 楼的回答后感觉整个人豁然开朗了。。
    aaronlam
        9
    aaronlam  
    OP
       2015-04-09 11:43:13 +08:00
    @luin 感谢!!!!
    ChiangDi
        10
    ChiangDi  
       2015-04-09 11:53:14 +08:00 via Android
    @aaronlam 对的,我理解错了, luin 那个是正解。
    aaronlam
        11
    aaronlam  
    OP
       2015-04-09 12:15:23 +08:00
    @RoshanWu 嗯,原来我是被 if 里的 var a 提升坑了。原来提升后 var a = void (); 然后 void(); 代表的是 f alse (ಠ .̫.̫ ಠ)
    iDelicious
        12
    iDelicious  
       2015-04-09 17:49:24 +08:00   ❤️ 1
    JS中函数和变量的声明会被提前执行
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3202 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 10:46 · PVG 18:46 · LAX 03:46 · JFK 06:46
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.