美文网首页程序员
关于ES2015转换es5遇到的‘this’变成‘undefin

关于ES2015转换es5遇到的‘this’变成‘undefin

作者: 进击的程序茗 | 来源:发表于2016-08-24 15:32 被阅读1373次

问题说明:

在使用压缩工具压缩并内置babelES2015转换成ES5打包js时,代码出现问题,代码简化后问题如下图1-1所示:

图1-1


this被识别成了undefined
以下为问题查找记录。

问题结果预说明:

之所以加个预说明是因为通篇记录对于该bug的查找过程,结果并没有达到完全解决,解决bug以去掉某些模块为前提,直接看结果请拉到最下方结果说明

问题查找过程:

图1-2


图上说导致原因为babel-plugin-transform-es2015-modules-commonjs,在进入该js的src目录下得index.js文件中,通过查找有一块代码如下图1-3:

图1-3


也就是说当allowTopLevelThis!=true时,会把this变成undefined,那么解决方式应该为把allowTopLevelThis设置属性值为true

图1-4

主要看第一种和第三种,第一种即在根目录添加.babelrc配置文件,第三种为在引入babel-core模块或者进行转换时进行配置.
  • 配置测试

环境说明:使用ezpack压缩如下代码:

(function(){
}).call(this)

babel-plugin-transform-es2015-modules-commonjs>lib>index.js中增加了三个console.log代码:如下图1-5所示:

图1-5


.babelrc中配置代码:
{
  presets: [
    ["es2015"]
  ],
  "plugins": [
    ["transform-es2015-modules-commonjs", {
      "allowTopLevelThis": true

    }]
  ]
}

但是控制台中打印出来的结果确不是我们想要的结果,打印结果如下1-6:

图1-6


控制台中仍然打印出了undefined,而不是只有true,也就是说我们配置的属性allowTopLevelThis并没有完全的起作用,更令人费解的是既打出了true又打出了undefined面对这种情况开始了更苦逼的查bug之路。
  • 继续查找bug

继续查找bug过程中主要分为两个部分:

1. 找到了代替的babel-preset-es2015-script

打开github连接直接就是readme文件,在.babelrc中配置如下,presets中不再配置es2015,而是配置es2015-script,代码如下:

{
  "presets": ["es2015-script"]
}

测试发现转换后的文件是call(this),而非call(undefined),转换成功,至于调试的babel-plugin-transform-es2015-modules-commonjs中的console.log,根本就没有出现,通过查看babel-preset-es2015-scriptindex.js文件,发现里面并没有引用babel-plugin-transform-es2015-modules-commonjs模块,这个提供了一个思路就是如果在babel-es2015-script中也不引用该模块,那么是否就可以解决问题了呢?然后我们回到babel-es2015-script中的index.js文件,如下图1-7所示:

图1-7

babel-es2015-script index.js ,我们注释红框内的代码,也就是把引用commonjs模块的部分全都注释掉,然后采用配置测试中的babelrc文件执行,控制台打印如下图1-8:

图1-8


注释掉该模块后就不再打印undefined,而true存在的原因则是因为配置文件中的属性更改起了作用,模块注释并不代表这个文件不存在,通过跟踪堆栈发现,当检索到.babelrc时,依然引用了该模块,这也可以解释为什么图1-6中打印出的信息为既有true又有undefined,也不知道为什么配置文件没有pk过原来的引用模块。

2. 查找babel-preset-2015 readme文件
readme文件如下图1-9所示:
图1-9


个人理解是在配置文件中增加loose配置,可以使得配置属性覆盖默认属性,此时.babelrc代码如下:
{
  presets: [
    ["es2015", {"loose": true}]
  ],
  "plugins": [
    ["transform-es2015-modules-commonjs", {
      "allowTopLevelThis": true

    }]
  ]
}
但是!

控制台中打出的信息仍然和图1-6一模一样,既有true,又有undefined,(内心崩溃泪流满面……),然后我把配置文件改成了这样:

{
  presets: [
    ["es2015", {"loose": true,"modules": false}]
  ],
  "plugins": [
    ["transform-es2015-modules-commonjs", {
      "allowTopLevelThis": true
    }]
  ]
}

结果正常通过,结果如图1-8,一切转换正常。这个配置和babel-preset-es2015-script起的作用是一样的,不引用modules模块,也就是说如果在es2015转换为es5的过程中不需要转换成这四种"amd", "umd", "systemjs", "commonjs"module type,也可以把模块去掉。

结果说明:

.babelrc中配置如下:

{
  presets: [
    ["es2015", {"loose": true,"modules": false}]
  ],
  "plugins": [
    ["transform-es2015-modules-commonjs", {
      "allowTopLevelThis": true
    }]
  ]
}

若不想放在babelrc中可以写在代码中transform转换时刻:

var babel = require('babel-core');
 var js =babel.transform(this.file, {
          presets:[['es2015',{loose:true,modules: false}]],
          plugins:[["transform-es2015-modules-commonjs", { allowTopLevelThis:true}]],
 });

即可把this改成undefined,但是通过配置去掉了es2015-modules-amdes2015-modules-commonjses2015-modules-systemjs
es2015-modules-umd四个模块。

不足之处:

由于测试时是在构建工具ezpack中测试,没有单独剥离babel环境,所以无法判定配置中属性"allowTopLevelThis": true无法pk过引用模块的原因是babel本身所致,还是ezpack引起的,需后续单独剥离babel环境继续测试,文中若有不足或错误之处,或者更好的解决方式,还请多多指出。
个人博客:
进击的程序茗

相关文章

网友评论

    本文标题:关于ES2015转换es5遇到的‘this’变成‘undefin

    本文链接:https://www.haomeiwen.com/subject/lyqosttx.html