• 请不要在回答技术问题时复制粘贴 AI 生成的内容
mytry
V2EX  ›  程序员

一个 JavaScript 挑战题,看看有多少人能做出来~

  •  1
     
  •   mytry · Nov 19, 2018 · 4785 views
    This topic created in 2912 days ago, the information mentioned may be changed or developed.

    在外部获取闭包内 key 变量的值。(不用考虑所有浏览器,Chrome 支持就可以)

    在线代码: https://jsfiddle.net/Ltse6nf4/

    21 replies  •  2018-11-20 11:28:09 +08:00
    suzic
    suzic
    Nov 19, 2018 via Android
    1
    不会。但感觉用 eval 能解
    jowan
    jowan
    Nov 19, 2018
    2
    ```
    recursion = () => {
    var key = apiX(100)
    return k = key <= 1 ? key : recursion()
    }

    try {
    recursion()
    } catch (e) {
    console.log(k)
    }
    hsfzxjy
    hsfzxjy
    Nov 19, 2018❤️3
    3
    ```
    function d () {
    try {
    return d()
    } catch (e) {
    return apiX()
    }
    }

    console.log(d());
    ```

    用爆栈引发异常
    jerrry
    jerrry
    Nov 19, 2018❤️1
    4
    这是什么字体?怎么感觉比 FiraCode 还顺眼。
    vicvinc
    vicvinc
    Nov 19, 2018
    5
    为啥 throw 一个 error 不会触发
    zbinlin
    zbinlin
    Nov 19, 2018
    6
    function x(fn) {
    const ret = fn(fn);
    if (ret === fn) {
    try {
    return x(fn);
    } catch (err) {
    return ret();
    }
    } else {
    return ret;
    }
    }

    console.log(x(apiX));
    zbinlin
    zbinlin
    Nov 19, 2018❤️1
    7
    精简下:

    function x(fn) {
    try {
    return x(fn(fn));
    } catch (err) {
    return fn();
    }
    }

    console.log(x(apiX));
    morethansean
    morethansean
    Nov 19, 2018
    8
    @jerrry #4
    祖传 Monaco
    mytry
    mytry
    OP
    Nov 19, 2018
    9
    @jowan
    @hsfzxjy
    @zbinlin 回答正确~ 💯
    mayday526
    mayday526
    Nov 19, 2018
    10
    @jerrry 用 FiraCode 的话,别人看我的代码要愣一下
    seki
    seki
    Nov 19, 2018❤️1
    11
    Math.random = () => 1
    lastpass
    lastpass
    Nov 19, 2018 via Android
    12
    回复 @seki 注意执行顺序呀。
    linxiaoziruo
    linxiaoziruo
    Nov 19, 2018
    13
    @hsfzxjy 验证了下代码,执行正确。但是我有个不明白的地方,爆栈应该只会出现在 d()这个函数的递归调用上,到了执行 apiX()的时候,栈应该重新记数了,应该不会触发 apix 的 catch。求解!
    FakeLeung
    FakeLeung
    Nov 19, 2018 via Android
    14
    Emmmmm 作为一个前端,看不懂,跑了。
    Sevenskey
    Sevenskey
    Nov 19, 2018
    15
    @linxiaoziruo 排队求解。顺便一说我发现只要 catch 中执行的函数的函数体内部有 try catch 且 try 中含有函数调用,就会在函数调用处抛爆栈的错;但如果这个函数体内部存在函数调用却没有 try catch,那么就不会抛错。。猜测也许是引擎的某些策略?
    autoxbc
    autoxbc
    Nov 19, 2018
    16
    @linxiaoziruo #13
    @Sevenskey #15

    猜测是不是这样

    执行代码
    function bomb()
    {
    try {
    return bomb()
    } catch(err) {
    return apiX()
    }
    }

    console.log( bomb() )

    爆栈阶段调用过程
    bomb_2 (){
    try {
    bomb_1 (){
    try {
    return bomb_0() ...
    } catch(err) {
    return apiX_0() ...
    }
    }
    } catch(err) {
    apiX_1 (){
    try {
    return internal() ...
    } catch(err) {
    return key
    }
    }
    }
    }

    实际流程
    => bomb_0(申请资源出错) => apiX_0(申请资源出错)
    => bomb_1(抛出错误) => apiX_1(正常执行)
    => internal(申请不到资源) => return key


    本题可解的关键是 return key 分支比 return internal() 少一级函数调用,如果两者调用长度相等,那么就失败了

    简单添加一句代码给 return key 分支加长调用链,令 apiX 为
    apiX = function(x) {
    try {
    return internal(x)
    } catch(err) {
    (function(){})() // 此句新加
    return key
    }
    }

    此时用上面方法爆栈是无法获取 key 的
    Sparetire
    Sparetire
    Nov 20, 2018 via Android
    17
    楼上正解,这里的关键就在于让调用 internal(x)的时候爆栈就行,只要调用栈足够深就爆栈,递归只是达成这一目的的方式
    ericgui
    ericgui
    Nov 20, 2018
    18
    @hsfzxjy 只有你的代码我能看懂
    mytry
    mytry
    OP
    Nov 20, 2018
    19
    公布答案~

    linxiaoziruo
    linxiaoziruo
    Nov 20, 2018
    20
    @mytry 老哥多来点这种趣味性的东西!
    razor1895
    razor1895
    Nov 20, 2018
    21
    apiX(new Error());
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   2574 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 65ms · UTC 11:17 · PVG 19:17 · LAX 03:17 · JFK 06:17
    ♥ Do have faith in what you're doing.