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

询问一个 JS 函数题

  •  1
     
  •   MLLB 2021-02-14 00:52:04 +08:00 4686 次点击
    这是一个创建于 1700 天前的主题,其中的信息可能已经有所发展或是发生改变。
    var a = 10; { a = 99; function a() { console.log(a); } a = 30; } console.log(a); 

    如上,请问为什么最终的打印结果是 99 呢?

    第 1 条附言    2021-02-14 17:36:22 +08:00
    各位,我也实属无奈。这是学校出的题目,老师说得也是似懂非懂,就来问各位大佬了。
    37 条回复    2021-02-19 16:09:27 +08:00
    xy90321
        1
    xy90321  
       2021-02-14 01:11:17 +08:00
    变量作用域往上找,找到啥就是啥。
    另外你什么浏览器跑的是 99 ?
    dousha99
        2
    dousha99  
       2021-02-14 01:40:24 +08:00
    @xy90321 在 NodeJS 15.8.0 的 REPL 里测试,确实输出 99. Firefox 85 下测试结果为 10.

    我原以为 JS 里没有这种未定义行为 /依赖于解释器实现的行为,今天是长见识了。
    shakaraka
        3
    shakaraka  
    PRO
       2021-02-14 02:10:20 +08:00
    写得太骚了。

    这题的关键是作用域吧?把 var 换成 let 就能得到 10 了,还有那两括号是什么意思还没找到,但是去掉括号一行行执行结果是 30 的,具体为什么我也不清楚,第一次见这样写,我悟了
    lichdkimba
        4
    lichdkimba  
       2021-02-14 02:19:23 +08:00   11
    firefox 10 chrome 99

    我服了 别出这种题目了行不行。。。。。。
    Building
        5
    Building  
       2021-02-14 02:28:11 +08:00   3
    请问有什么需求要求一定要这样写吗?写个代码都搞得跟八股文似的。
    Caballarii
        6
    Caballarii  
       2021-02-14 02:38:28 +08:00
    js 是世界上最好的语言
    POPOEVER
        7
    POPOEVER  
       2021-02-14 03:02:15 +08:00
    {} 的写法相当于 var
    kaiki
        8
    kaiki  
       2021-02-14 03:11:34 +08:00
    自从我知道不同浏览器的 JS 代码有不同的支持的时候,就不会去写这种花里胡哨的代码了。
    能跑出一样的结果就行,反正是在客户的机子上跑,又不占我服务器,效率低点就低点。
    mrochcnnnnn
        9
    mrochcnnnnn  
       2021-02-14 03:29:19 +08:00 via iPhone
    @Caballarii 论坛气氛组就位,Java 不服
    iugo
        10
    iugo  
       2021-02-14 09:31:09 +08:00   1
    ```js
    var a = 10;

    for (let i = 0; i < 1; i++) {
    a = 99;

    function a() {
    console.log(a);
    }

    a = 30;
    }

    console.log(a);
    ```

    这样看我们就容易接受一点.

    我预期应该是返回 10 的, 之所以返回 99 可能和 V8 在作用域内没有函数声明进行提升有关.

    刚好, 我们要强调, 在写 JS 的时候有如下要注意:

    1. 在函数声明时, 避免重名.
    2. 函数声明时, 尽量在顶级, 否则使用箭头函数.

    在 ESLint 下或者 TypeScript 下, 基本是写不出这么 "错误的" 代码的. 肯定会在写的时候报错.
    across
        11
    across  
       2021-02-14 10:03:34 +08:00 via iPhone
    看结果明白为什么(同名函数区域覆盖)。
    不过具体规则懒得找了,现在都用 let 而且搞同名写法也会被骂的...
    oott123
        12
    oott123  
       2021-02-14 11:14:36 +08:00 via Android   3
    finalwave
        13
    finalwave  
       2021-02-14 11:38:27 +08:00
    Sample
        14
    Sample  
       2021-02-14 11:59:05 +08:00   4
    新时代八股
    大清早就亡了
    es2020 都来了
    let 也可以考察作用域
    该公司的代码难道也这样写吗?
    茴香豆的茴字就贵公司知道有四种写法?

    非要拿着旧时代的裹脚布狂舔,真的不恶心吗
    f0rger
        15
    f0rger  
       2021-02-14 13:04:49 +08:00 via iPhone
    第一眼也是应该不是 99
    我逆向推,得到 across 的答案。
    不过这写法真的是吐了……
    crab
        16
    crab  
       2021-02-14 13:37:55 +08:00
    @lichdkimba C 中的 多次++ --
    AV1
        17
    AV1  
       2021-02-14 16:53:04 +08:00
    尽量用函数表达式 const func = ()=>{...},而不是函数声明 function func(){...}
    rodrick
        18
    rodrick  
       2021-02-14 17:04:36 +08:00
    别搞这种题了。。真的累
    MLLB
        19
    MLLB  
    OP
       2021-02-14 17:33:39 +08:00
    @lichdkimba 我也实属无奈。要做。
    MLLB
        20
    MLLB  
    OP
       2021-02-14 17:34:11 +08:00
    @Building 可以理解为学校的题目。
    across
        21
    across  
       2021-02-14 17:55:16 +08:00 via iPhone
    这种题目拿来做分析理解其实没什么问题,可以认识到 js 的缺陷表现。
    你不知道的 js 第一本有专区讲过这些问题
    zhoudaiyu
        22
    zhoudaiyu  
    PRO
       2021-02-14 18:01:05 +08:00 via iPhone
    int a = 5; a= ++++++a++++++++; cout << a;
    cyberpoint
        23
    cyberpoint  
       2021-02-14 18:01:35 +08:00
    现在出这种题目的都是 NT
    ttoott200
        24
    ttoott200  
       2021-02-14 18:28:49 +08:00   4
    好神奇! a = 99 改变了全局变量 a,函数声明 function a() 相当于以 let 方式创建了一个局部变量 a,后面的 a = 30 改变了局部变量,不会影响到全局变量,最后输出的 a 是 99 。
    Kininaru
        25
    Kininaru  
       2021-02-14 18:45:18 +08:00 via Android
    如果我同事写这种代码给我看,我会考虑偷偷拔掉他的头发
    AndyAO
        26
    AndyAO  
       2021-02-14 18:46:58 +08:00
    学校里居然开始教 Javascript 了 !

    请问楼主你是什么学校?什么专业?
    autoxbc
        27
    autoxbc  
       2021-02-14 19:04:44 +08:00
    @Caballarii #6 Javascript 天天抄别人的语言特性,早晚会抄成最好的语言
    deepall
        28
    deepall  
       2021-02-14 20:06:25 +08:00
    safari 30
    chrome 99
    哈哈哈
    justin2018
        29
    justin2018  
       2021-02-14 20:29:45 +08:00
    我这有的学校外聘老师讲课 讲一次课 1k 左右

    一个月 几节课~
    wish8023
        30
    wish8023  
       2021-02-14 20:39:21 +08:00
    wish8023
        31
    wish8023  
       2021-02-14 20:44:47 +08:00
    @wish8023
    额,自己看调用栈吧!
    https://sm.ms/image/JZmKwI8Pgu3pWBD
    wish8023
        32
    wish8023  
       2021-02-14 20:47:33 +08:00
    调用栈:
    jinliming2
        33
    jinliming2  
       2021-02-15 00:25:34 +08:00
    IE 下、旧 IE 下打印的是 function a() { console.log(a); }:
    https://i.loli.net/2021/02/15/S97y1WPJxCRlAj2.png
    jinliming2
        34
    jinliming2  
       2021-02-15 00:28:29 +08:00
    但是添加 "use strict" 之后就打印 10 了:
    ![image.png]( https://i.loli.net/2021/02/15/erJPX7dDu35RVq1.png)
    mxT52CRuqR6o5
        35
    mxT52CRuqR6o5  
       2021-02-15 00:38:07 +08:00
    现在上学没办法,毕业之后不要太研究这种东西,不然就成孔乙己了
    lixingjun
        36
    lixingjun  
       2021-02-15 10:36:59 +08:00
    实战中这种问题几乎碰不到,还是多实现一些确定的功能,代码水平才能真正进步
    Roger006
        37
    Roger006  
       2021-02-19 16:09:27 +08:00
    和朋友讨论调试后,对非严格模式下的结果有个猜测。修改原有代码为以下。都是在桌面 chrome v88 测试出来的情况。
    0.
    1. var a = 10;
    {
    2. console.log(a);
    3. a = 99;
    4. function a(x) {}
    5. a = 12;
    6. function a() {}
    7. a = 30;
    8. console.log(a);
    }
    9.console.log(a);
    代码运行到 [打断点地方]
    0 位置,global=>a//undefined
    1 位置 global => a//undefined
    2 位置 g=>a//10 block=>a// function a(){}
    3 位置 g=>a//10 block=>a// function a(){}
    4 位置 g=>a//10 block=a//99
    5 位置 g=>a//99 b=>a//99
    6 位置 g=>a//99 b=>a//12
    7 位置 g=>a//12 b=>a//12
    8 位置 g=>a//12 b=>a//30
    9 位置 g=>a//12

    暂时的猜测是,非严格模式下的块儿内函数声明,会有提升覆盖,但运行到同名函数声明位置的时候,当前的同名变量的值会传递到全局
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1361 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 38ms UTC 23:59 PVG 07:59 LAX 16:59 JFK 19:59
    Do have faith in what you're doing.
    ubao 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