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 · 127 天前 · 2846 次点击
    这是一个创建于 127 天前的主题,其中的信息可能已经有所发展或是发生改变。
    var a = 10; {
        a = 99;
    
        function a() {
            console.log(a);
        }
        a = 30;
    }
    console.log(a);
    

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

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

    我原以为 JS 里没有这种未定义行为 /依赖于解释器实现的行为,今天是长见识了。
    wunonglin
        3
    wunonglin   127 天前
    写得太骚了。

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

    我服了 别出这种题目了行不行。。。。。。
    Building
        5
    Building   127 天前   ❤️ 3
    请问有什么需求要求一定要这样写吗?写个代码都搞得跟八股文似的。
    Caballarii
        6
    Caballarii   127 天前
    js 是世界上最好的语言
    POPOEVER
        7
    POPOEVER   127 天前
    {} 的写法相当于 var
    kaiki
        8
    kaiki   127 天前
    自从我知道不同浏览器的 JS 代码有不同的支持的时候,就不会去写这种花里胡哨的代码了。
    能跑出一样的结果就行,反正是在客户的机子上跑,又不占我服务器,效率低点就低点。
    mrochcnnnnn
        9
    mrochcnnnnn   127 天前 via iPhone
    @Caballarii 😂😂😂😂论坛气氛组就位,Java 不服
    iugo
        10
    iugo   126 天前   ❤️ 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   126 天前 via iPhone
    看结果明白为什么(同名函数区域覆盖)。
    不过具体规则懒得找了,现在都用 let 而且搞同名写法也会被骂的...
    oott123
        12
    oott123   126 天前 via Android   ❤️ 3
    finalwave
        13
    finalwave   126 天前
    Sample
        14
    Sample   126 天前   ❤️ 4
    新时代八股
    大清早就亡了
    es2020 都来了
    let 也可以考察作用域
    该公司的代码难道也这样写吗?
    茴香豆的茴字就贵公司知道有四种写法?

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

    请问楼主你是什么学校?什么专业?
    autoxbc
        27
    autoxbc   126 天前
    @Caballarii #6 JavaScript 天天抄别人的语言特性,早晚会抄成最好的语言
    deepall
        28
    deepall   126 天前
    safari 30
    chrome 99
    哈哈哈
    justin2018
        29
    justin2018   126 天前
    我这有的学校外聘老师讲课 讲一次课 1k 左右

    一个月 几节课~
    wish8023
        30
    wish8023   126 天前
    wish8023
        31
    wish8023   126 天前
    @wish8023
    额,自己看调用栈吧!
    https://sm.ms/image/JZmKwI8Pgu3pWBD
    wish8023
        32
    wish8023   126 天前
    调用栈:
    jinliming2
        33
    jinliming2   126 天前
    IE 下、旧 IE 下打印的是 function a() { console.log(a); }:
    https://i.loli.net/2021/02/15/S97y1WPJxCRlAj2.png
    jinliming2
        34
    jinliming2   126 天前
    但是添加 "use strict" 之后就打印 10 了:
    ![image.png]( https://i.loli.net/2021/02/15/erJPX7dDu35RVq1.png)
    mxT52CRuqR6o5
        35
    mxT52CRuqR6o5   126 天前
    现在上学没办法,毕业之后不要太研究这种东西,不然就成孔乙己了
    lixingjun
        36
    lixingjun   125 天前
    实战中这种问题几乎碰不到,还是多实现一些确定的功能,代码水平才能真正进步
    Roger006
        37
    Roger006   121 天前
    和朋友讨论调试后,对非严格模式下的结果有个猜测。修改原有代码为以下。都是在桌面 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

    暂时的猜测是,非严格模式下的块儿内函数声明,会有提升覆盖,但运行到同名函数声明位置的时候,当前的同名变量的值会传递到全局
    关于   ·   帮助文档   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   2624 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 31ms · UTC 01:05 · PVG 09:05 · LAX 18:05 · JFK 21:05
    ♥ Do have faith in what you're doing.