一个神奇的 js 问题 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
atwoodSoInterest
V2EX    程序员

一个神奇的 js 问题

  •  1
     
      atwoodSoInterest 2019-12-03 17:59:37 +08:00 3025 次点击
    这是一个创建于 2186 天前的主题,其中的信息可能已经有所发展或是发生改变。
    今天遇到了一个神奇的 js 问题,debug 到最后发现了问题,但是不知道原理,有大佬能解释下吗?

    function func() {
    var s = "heheda";
    $.ajax({
    type: "post",
    dataType: "text",
    contentType: "application/json; charset=",
    url: "",
    data: JSON.stringify([{}]),
    success: function () {
    },
    error: function (ex) {
    //debugger;
    s = "inner heheda";
    }
    });

    $.ajax({
    type: "post",
    dataType: "text",
    contentType: "application/json; charset=",
    url: "",
    data: JSON.stringify([{}]),
    success: function () {
    },
    error: function (ex) {
    //debugger;
    bug = "WTF?!";
    }
    });
    }

    测试环境:win10 chrome 78.0.3904.108 (正式版本) ( 64 位)

    定义一个这样的函数,调用之后在 debug 模式下发现,在使用了外部变量 s 的 ajax callback 里面,s 是可以显示值的。但是在没有使用外部变量 s 的 ajax callback 里面,s 就变成了 undefined !这。。。也太神奇了吧
    (不要用 console 打印哦,因为打印也用到了变量 s )
    第 1 条附言    2019-12-03 19:37:49 +08:00

    ie必须指定url,直接复制这段到控制台运行就行了

    function func() { var s = "heheda"; $.ajax({ type: "post", dataType: "text", contentType: "application/json; charset=", url: "http://www.baidu.com", data: JSON.stringify([{}]), success: function () { }, error: function (ex) { debugger; s = "inner heheda"; } }); $.ajax({ type: "post", dataType: "text", contentType: "application/json; charset=", url: "http://www.baidu.com", data: JSON.stringify([{}]), success: function () { }, error: function (ex) { debugger; bug = "WTF?!"; } }); } func(); 
    第 2 条附言    2019-12-03 19:47:23 +08:00

    结果果然如 @xiangyuecn 大佬所说,是浏览器行为,换ie就没有这个问题了,是chrome自己的行为。结贴,感谢@xiangyuecn

    突然感慨,热帖 程序员总喜欢自断后路,难怪职业生涯只能到 35 岁 中的那种自我保护,从小了看似乎能保全一时,但是往大了看,其实是一种自我投毒。即使真有少部分人能用这种手段保全职位,但对于大多数情况和大多数人来说,都是没有前途的。

    14 条回复    2019-12-05 08:41:55 +08:00
    p8YFk4f3E8SJ3aEv
        1
    p8YFk4f3E8SJ3aEv  
       2019-12-03 18:02:34 +08:00
    没使用变量 S,可不就是打印 undefined 吗,未定义啊
    atwoodSoInterest
        2
    atwoodSoInterest  
    OP
       2019-12-03 18:05:55 +08:00
    @f056917 外部变量 s 的作用域会因为内部使不使用而改变吗?你可以把 debugger 注释放开,调试一下。
    guoguo2003guo
        3
    guoguo2003guo  
       2019-12-03 18:09:36 +08:00
    里面的 s 也定义一下呗
    lqzhgood
        4
    lqzhgood  
       2019-12-03 18:10:25 +08:00 via Android   2
    不知道 lz 在说啥…
    gaoryrt
        5
    gaoryrt  
       2019-12-03 18:20:32 +08:00
    变量提升
    s = 123 第一步相当于 var s = undefined 放到第一行,执行到的时候再赋值 123
    debugger 中断的时候可不就是 undefined 嘛
    xiangyuecn
        6
    xiangyuecn  
       2019-12-03 18:42:59 +08:00   2
    换 ie 试试应该就没有这个问题了。怀疑是 chrome 对这种闭包内压根没有作用的代码进行了优化,新版本浏览器经常 debugger 会出现这种,不过手动展开作用域里面的 Closure 会发现是有值的,手动存一个全局变量就能得到实际的值。
    atwoodSoInterest
        7
    atwoodSoInterest  
    OP
       2019-12-03 19:48:22 +08:00
    @xiangyuecn 正解!感谢
    chairuosen
        8
    chairuosen  
       2019-12-03 19:54:23 +08:00
    是 chrome 的优化,很早(起码 2-3y)就有了
    caola
        9
    caola  
       2019-12-03 21:06:14 +08:00
    虽然不知道具体的表达,
    callback 是异步执行的,你想直接在 callback 里面打印是不是有点搞笑了。。。
    fox0001
        10
    fox0001  
       2019-12-03 22:19:06 +08:00
    @lqzhgood #4 确实不知道…我试了一下,可以在 callback 里改变 s 的值
    atwoodSoInterest
        11
    atwoodSoInterest  
    OP
       2019-12-04 08:35:25 +08:00
    @lqzhgood @caola @fox0001 我再解释一下,示例代码中的变量 s 的作用域应该在整个 func 函数中,两个 ajax callback 也都应该在作用域内。但是在 chrome 浏览器的 debug 模式下,就会发现神奇的一幕:使用了变量 s 的 callback 中,控制台可以输入 s,显示有值;没有使用变量 s 的 callback 中,控制台输出 s,显示 s is not defined。
    laravel
        12
    laravel  
       2019-12-04 11:31:48 +08:00
    setInterval('debugger', 1000);
    xingyue
        13
    xingyue  
       2019-12-04 23:48:49 +08:00
    @xiangyuecn #6 你好,图 1 和图 2 是我复现楼主的代码,确实在[[Scopes]]中 Closure 找到了未使用的变量;但是图 3 中我注释掉了使用内部变量的代码,再次查看闭包返回的函数 f1 发现[[Scopes]]中 Closure 都没了,请问这是怎么回事
    (图 1)

    (图 2)

    (图 3)
    xiangyuecn
        14
    xiangyuecn  
       2019-12-05 08:41:55 +08:00
    @xingyue #13 也许图 3 这个 Closure 是和变量一样被优化掉了吧,f2 函数内没有任何东西需要用到闭包。加一点别的什么的构成引用,应该就会显示这个 Closure
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     962 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 26ms UTC 19:01 PVG 03:01 LAX 11:01 JFK 14:01
    Do have faith 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