关于ES2015转换es5遇到的‘this’变成‘undefined’问题查找记录

问题说明:

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

图1-1


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

问题结果预说明:

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

问题查找过程:

  • 问题原因

    通过搜索,在github issue查找到对于该问题的讨论github issue:this is undefined for React components #37;issue中对于该问题讨论如下图1-2:

图1-2

关于ES2015转换es5遇到的‘this’变成‘undefined’问题查找记录_第1张图片

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

图1-3

关于ES2015转换es5遇到的‘this’变成‘undefined’问题查找记录_第2张图片

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

  • 属性配置

    通过 babel-plugin-transform-es2015-modules-commonjs的readme文件可以找到更改配置的方式有三种如图1-4:

图1-4

关于ES2015转换es5遇到的‘this’变成‘undefined’问题查找记录_第3张图片
主要看第一种和第三种,第一种即在根目录添加 .babelrc配置文件,第三种为在引入 babel-core模块或者进行转换时进行配置.

  • 配置测试

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

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

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

图1-5

关于ES2015转换es5遇到的‘this’变成‘undefined’问题查找记录_第4张图片

.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

关于ES2015转换es5遇到的‘this’变成‘undefined’问题查找记录_第5张图片
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

关于ES2015转换es5遇到的‘this’变成‘undefined’问题查找记录_第6张图片

个人理解是在配置文件中增加 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-amd、es2015-modules-commonjs、es2015-modules-systemjs
、es2015-modules-umd四个模块。

不足之处:

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

你可能感兴趣的:(关于ES2015转换es5遇到的‘this’变成‘undefined’问题查找记录)