三个 Javascript 例子中的函数提升为何导致不同的输出? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
klion
V2EX    Node.js

三个 Javascript 例子中的函数提升为何导致不同的输出?

  •  
  •   klion 2023-08-21 20:27:40 +08:00 2545 次点击
    这是一个创建于 847 天前的主题,其中的信息可能已经有所发展或是发生改变。

    问题描述

    我在学习 Javascript 的函数提升( hoisting )时,遇到了三个看似相似但输出不同的例子。根据函数提升的原理,这三个例子的输出应该是相同的,越想越觉得奇怪啊

    例子 1

    var a = 0; console.log("1 a:", a); if(true){ a = 1; function a() {} a = 5; console.log("2 a:", a); } console.log("3 a:", a); 

    经过验证,输出结果为:

    1 a: 0 2 a: 5 3 a: 1 

    例子 2

    var a = 0; console.log("1 a:", a); if(true){ a = 1; a = 5; console.log("2 a:", a); function a() {} } console.log("3 a:", a); 

    经过验证,输出结果为:

    1 a: 0 2 a: 5 3 a: 5 

    例子 3

    var a = 0; console.log("1 a:", a); if(true){ function a() {} a = 1; a = 5; console.log("2 a:", a); } console.log("3 a:", a); 

    经过验证,输出结果为:

    1 a: 0 2 a: 5 3 a: f a() {} 

    问题

    1. 这几个例子在函数提升方面有何不同?
    2. 为什么每个例子的输出都不相同?
    16 条回复    2023-09-05 11:41:41 +08:00
    Yumwey
        1
    Yumwey  
       2023-08-21 21:15:34 +08:00   1
    1. 主要是块和全局作用域在 es5 的非严格模式下混淆了,你每一步解析一下提升过程,注意块作用域内 console 输出一直都是 a 的赋值,但是声明式的 Function a 在提升后对全局作用域 a 的引用关系才是 3a 结果, var / 声明式 Function 的提升优先级
    2. 加个 'use strict' 就一样了
    3. 其实不太需要考虑这个了,直接用 let, const 就好了
    zhouyg
        2
    zhouyg  
       2023-08-21 21:27:05 +08:00   4
    建议不学这种糟粕
    klion
        3
    klion  
    OP
       2023-08-21 21:29:34 +08:00
    @zhouyg 原因是以前一同学想测试 GPT4 的能力,结果 GPT4 答不上来,我越看也越觉得怪,就上论坛发帖了。stackoverflow 上都说是历史遗留问题,https://stackoverflow.com/questions/58619924/function-declaration-in-block-moving-temporary-value-outside-of-block
    mxT52CRuqR6o5
        4
    mxT52CRuqR6o5  
       2023-08-21 21:42:50 +08:00 via Android
    不要再研究 sloppy mode 的东西了
    我跟你说你这几个 case 在上古浏览器里还有另外不同的表现的
    Rocketer
        5
    Rocketer  
       2023-08-22 00:18:41 +08:00 via iPhone
    研究屎山是为了消除它,而不是让自己适配它。

    对于已经消除的屎山,还拿他做题玩嘛呢?有公司面试题出这个我都直接怼回去,也没耽误我拿 offer
    LUO12826
        6
    LUO12826  
       2023-08-22 01:46:49 +08:00
    欢迎使用 Safari ,Safari 里三者输出是一样的。在块作用域内定义用 function 定义函数是 JS 中的标准未定义行为,取决于 JS 引擎的实现
    iOCZ
        7
    iOCZ  
       2023-08-22 09:13:02 +08:00
    例子三怎么解释啊?
    stillsilly
        8
    stillsilly  
       2023-08-22 10:16:05 +08:00
    吃饱了撑的
    xiangyuecn
        9
    xiangyuecn  
       2023-08-22 10:27:34 +08:00
    你编写的奇怪的代码正在以奇怪的方式运行。

    第一行放个 'use strict' 确实能解决不少麻烦。

    同一个作用域下不要使用重名的变量,减轻自己的负担。

    拒绝使用 const 关键字,我都写 js 了,还 const const const 。
    c3de3f21
        10
    c3de3f21  
       2023-08-22 11:10:59 +08:00
    @zhouyg 哎,我也是这么认为的,明明有更好的方式来规避这种问题比如 let/const ,可偏偏有公司把这些放到面试题里去。
    zangbianxuegu
        11
    zangbianxuegu  
       2023-08-22 13:42:21 +08:00
    @iOCZ 函数声明在全局也创建了同名变量,声明时改变了全局同名变量
    iOCZ
        12
    iOCZ  
       2023-08-22 15:05:56 +08:00
    只能这么认为了,就是函数声明提升 var a = function(){},然后紧接着是 window.a = a;然后原来声明之前的 a 赋值,都是 window.a 赋值,函数声明之后的都是 a 赋值。这样能符合所有结果。
    liuidetmks
        13
    liuidetmks  
       2023-08-22 18:29:06 +08:00
    boring , i +++++i 等于几?
    humbass
        14
    humbass  
       2023-08-22 21:31:18 +08:00
    es6 给了 let,const ,就是用来解决这些问题体操的。
    Pythoner666666
        15
    Pythoner666666  
       2023-09-01 11:28:21 +08:00
    2023 年了 还在纠结这种问题
    xingguang
        16
    xingguang  
       2023-09-05 11:41:41 +08:00
    我之前看一个视频说 function 的提升有时候很奇怪,规范里都没有定,所以这里是引擎按照自己的理解实现的,所以这样的 function 提升在不同浏览器的结果可能都不一样,所以学习这种提升实在是没必要,面试真遇到了也只能可惜的放弃吧
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5188 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 41ms UTC 07:47 PVG 15:47 LAX 23:47 JFK 02:47
    Do have fith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86