进入debugger调试时,this 输出 undefined的问题,箭头函数与babel造成的调试不便 |
您所在的位置:网站首页 › dev如何调试函数内部 › 进入debugger调试时,this 输出 undefined的问题,箭头函数与babel造成的调试不便 |
进入debugger调试时, this 输出 undefined的问题,箭头函数与babel造成的调试不便
引言问题区分1.箭头函数内的 this 和封闭的局部变量一样2.箭头函数内的 this 被babel 打包后重命名了3.正确获取this 解决方案
引言
之前用VUE开发的时候经常遇到,用 chrome 的调试工具进入页面 debugger 的时候,用 console.log(this) 能输出 this的值。但是在断点过程中,用鼠标移动到 this 上显示的确是 undefined(在控制台中输出 this 也是 undefined)。说实话,当时是因为影响并不大,也没在意,也没探究过具体的原因。昨天刚好手上任务完成,就抽了一些时间去仔细找找具体的原因以及解决方案。 问题区分对的,你没看错,这个问题要区分一下,因为这个问题并不只是一个问题。这里涉及到多个问题,我在查找原因的时候就发现有人问类似的问题。当我知道具体原因后就发现,问的以及回答的存在牛头不对马嘴的情况。 1.箭头函数内的 this 和封闭的局部变量一样 这里不展开分享箭头函数,主要讲一点,箭头函数里的 this 跟封闭的局部变量一样,如果箭头函数内部未显式的写出 this,进入这个箭头函数内部的断点,this 输出的是 undefined,看下面这个例子你就知道了。 至于出现原因就是因为chrome调试器的优化,如果未在函数内部引用局部变量(这里是this),这个变量就不会存储在此函数上下文对象中。所以总结就是箭头函数内部的this(这里不谈指向),生存周期与普通函数的封闭局部变量一样,都是未显式引用输出就是undefined(针对chrome 调试,火狐不会)。 有兴趣的小伙伴可以进入这篇 Chrome调试器为何认为封闭的局部变量未定义?中看看其他牛人的讨论,如果英语足够好也可以进原英文链接 Why does Chrome debugger think closed local variable is undefined? 相信这里能完全解决你此问题的疑惑。 2.箭头函数内的 this 被babel 打包后重命名了刚了解到这个问题的时候就去babel官网看了,找到 Why is this being remapped to undefined? 这样一个问题,我兴奋的以为,我找到了答案。但被事实狠狠打大了一把脸。这里问的主要是因为 babel ES2015模块是隐式严格模式的,所以即使是上方第一个问题用普通函数输出也是undefined(严格模式下用window. 调用函数,函数内部this 才会指向 Window 对象)。 回到我们的具体问题。进入断点时 console.log(this) 输出了内容,而直接在控制台写 this 执行或者鼠标移到断点处的 this 上显示 undefined是什么原因(这里不是探究为什么显示undefined了,而是为什么和代码中console.log(this) 输出的不一致,即使解决了输出undefined ,也就是移除严格模式,这里的this 应该也只是输出 Window对象,而不是我们当前运行环境中的比如Vue 这个组件对象)。 因为在项目中使用了babel。比如箭头函数就会被打包成普通函数,而this 指向就会用变量保存来代替,比如_this,_this2之类的。 我把代码例子贴出来大家就知道了,我用的vue 就用vue使用的一个箭头函数的例子解释。 /* 这个代码是vue methods 钩子下的一个函数,是我的源代码。*/ handle() { this.add().then(() => { console.log(this.number); debugger; }); } /* 这个代码就是上方代码在项目运行中,打包后的代码 */ handle: function handle() { var _this2 = this; this.add().then(function () { console.log(_this2.number); debugger; }); }下面的截图就是在运行中Sources 下进入断点的代码 这里为什么进入断点时在.vue文件中,实际是在.js文件呢,是因为vue 配置webpack 的 源映射 source-map 的默认配置。默认配置在打包速度上稍慢,但是胜在调试更加方便。也可以改成其他配置,点击上面的链接可以进入官网查看详细配置,这里就不谈了。 .vue 就是断点这里this没有指向值,如果想调试查看你想要的 this 值,可以在cjs.js这个文件里看,不过因为打包后和实际写的源代码有较多差异你也可以在Watch 下添加_this2 (为什么是_this2,接着看完吧) 监听,比如下面的例子。 也可以像我这样,进入断点时在控制台输入 _this 这里提示我 是 _this6,如果实在不找不到就接着看下面。 说到底难道没有不添加Watch 的办法吗,而且这里还是不能把鼠标移动到this 上提示预期值,其实也是有一些比较婉转的解决方案的。 第一个,如果项目不用向下兼容,那么推荐不要使用babel了,嘿嘿,这个简单粗暴。(以下动图演示能看到这里的运行代码就没被babel 打包,因为我把babel 移除了) 然后在.babelrc或者是babel.config.js 配置文件中加入 plugins: [["transform-es2015-arrow-functions", { spec: true }]]运行你的代码,进入断点就会发现。 此方法是参考 loganfsmyth 在Stack Overflow上回答一个问题的答案,有兴趣的同学可以点进去看。再加上国内复刻网站的中文链接。 以上解释如果描述不当或欠缺,欢迎指正,谢谢。 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |