如何阻止 babel 将“this"转换为“undefined"(并插入“use strict") [英] How to stop babel from transpiling 'this' to 'undefined' (and inserting "use strict")

查看:37
本文介绍了如何阻止 babel 将“this"转换为“undefined"(并插入“use strict")的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

编辑:这与与粗箭头无关.这也不是将 this 传递给 IIFE.这是一个与转译器相关的问题.

所以我为我正在开发的一个小应用程序创建了一个简单的发布订阅.我在 ES6 中编写它以使用传播/休息并省去一些麻烦.我使用 npm 和 gulp 对其进行设置以对其进行转译,但它让我发疯.

我把它做成了一个浏览器库,但意识到它可以在任何地方使用,所以我决定让它兼容 Commonjs 和 AMD.

这是我的代码的精简版:

(function(root, factory) {if(typeofdefine === 'function' &&define.amd) {定义([],函数(){返回(root.simplePubSub = factory())});} else if(typeof module === 'object' && module.exports) {module.exports = (root.simplePubSub = factory())} 别的 {root.simplePubSub = root.SPS = factory()}}(这个,函数(){//返回 SimplePubSub});

但无论我尝试什么(例如将 this 设为变量并传递它),它都会将其设置为 undefined.

}(未定义,function() {

这可能与 Babel 不知道 这个 会是什么并转译它有关,但我可以采取其他任何方法吗?

UPDATE:传递 }((window || module || {}), function() { 而不是 this 似乎有效. 但我不确定这是最好的方法.

解决方案

For Babel >= 7.x

ES6 代码有两种处理方式:

  • "script" - 当您通过 <script> 或任何其他标准 ES5 加载文件方式加载文件时
  • "module" - 当文件作为 ES6 模块处理时

在 Babel 7.x 中,文件默认被解析为模块".给你带来麻烦的是,在 ES6 模块中,thisundefined,而在 "script" 的情况下,这取决于在环境中,例如浏览器脚本中的 window 或 CommonJS 代码中的 exports.同样的,"module" 文件是自动严格的,所以 Babel 会插入 "use strict";.

在 Babel 7 中,如果你想避免这种行为,你需要告诉 Babel 你的文件是什么类型.最简单的选择是使用 "sourceType" 选项在你的 Babel 选项中设置 sourceType: "unambiguous" ,它本质上告诉 Babel 根据 import 的存在来猜测类型(脚本 vs 模块)export 语句.主要的缺点是,拥有一个不使用 importexport 的 ES6 模块在技术上没有问题,并且这些模块会被错误地视为脚本.另一方面,这真的不常见.

或者,您可以使用 Babel 7 的 "overrides" 将特定文件设置为脚本的选项,例如

覆盖:[{测试:./vendor/something.umd.js",源类型:脚本",}],

这两种方法都允许 Babel 知道某些文件是 script 类型,因此不应该将 this 转换为 undefined.>

对于巴别塔 <7.x

ES6 代码有两种处理方式:

  • "script" - 当您通过 <script> 或任何其他标准 ES5 加载文件方式加载文件时
  • "module" - 当文件作为 ES6 模块处理时

当使用 Babel 6 和 babel-preset-es2015(或 Babel 5)时,Babel 默认假设它处理的文件是 ES6 模块.给你带来麻烦的是,在 ES6 模块中,thisundefined 并且文件都是严格的,而在脚本"的情况下,this 因环境而异,例如浏览器脚本中的 window 或 CommonJS 代码中的 exports.

如果您使用 Babel,最简单的选择是在没有 UMD 包装器的情况下编写代码,然后使用 Browserify 之类的工具捆绑您的文件,以自动为您添加 UMD 包装器.Babel 还提供了一个 babel-plugin-transform-es2015-modules-umd.两者都面向简单性,因此如果您想要定制的 UMD 方法,它们可能不适合您.

或者,您需要在 babel-preset-es2015,确保排除模块处理 babel-plugin-transform-es2015-modules-commonjs 插件.请注意,这也将停止自动添加 use strict 因为它也是 ES6 规范的一部分,您可能需要重新添加 babel-plugin-transform-strict-mode 自动保持您的代码严格.

babel-core@6.13 开始,预设可以选择选项,所以你也可以这样做

<代码>{预设":[[ "es2015", { "modules": false } ]]}

在您的 Babel 配置 (.babelrc) 中使用 babel-preset-es2015 并禁用模块处理.

EDIT: This is not about fat arrows. It's also not about passing this to an IIFE. It's a transpiler-related question.

So I've created a simple pub-sub for a little app I'm working on. I wrote it in ES6 to use spread/rest and save some headaches. I set it up with npm and gulp to transpile it but it's driving me crazy.

I made it a browser library but realized it could be used anywhere so I decided to make it Commonjs and AMD compatible.

Here's a trimmed down version of my code:

(function(root, factory) {
 if(typeof define === 'function' && define.amd) {
    define([], function() {
        return (root.simplePubSub = factory())
    });
  } else if(typeof module === 'object' && module.exports) {
    module.exports = (root.simplePubSub = factory())
  } else {
    root.simplePubSub = root.SPS = factory()
  }
}(this, function() {
 // return SimplePubSub
});

But no matter what I try (such as making this a variable and passing it) it sets it to undefined.

}(undefined, function() {

It probably has something to do with Babel not knowing what this will be and transpiling it away but is there any other approach I can take?

UPDATE: Passing }((window || module || {}), function() { instead of this seems to work. I'm not sure this is the best approach though.

解决方案

For Babel >= 7.x

ES6 code has two processing modes:

  • "script" - When you load a file via a <script>, or any other standard ES5 way of loading a file
  • "module" - When a file is processed as an ES6 module

In Babel 7.x, files are parsed as "module" by default. The thing that is causing you trouble is that in an ES6 module, this is undefined, whereas in the "script" case, this varies depending on the environment, like window in a browser script or exports in CommonJS code. Similarly, "module" files are automatically strict, so Babel will insert "use strict";.

In Babel 7, you'll need to tell Babel what type your file is if you want to avoid this behavior. The simplest option would be to use the "sourceType" option to set sourceType: "unambiguous" in your Babel options, which essentially tells Babel to guess the type (scripts vs module), based on the presence of import and export statements. The primary downside there being that it's technically fine to have an ES6 module that doesn't use import or export, and those would be incorrectly treated as scripts. On the other hand, that's really not that common.

Alternatively, you can use Babel 7's "overrides" option to set specific files as scripts, e.g.

overrides: [{
  test: "./vendor/something.umd.js",
  sourceType: "script",
}],

Either approach allows Babel to know that some files are script types, and thus shouldn't have this converted to undefined.

For Babel < 7.x

ES6 code has two processing modes:

  • "script" - When you load a file via a <script>, or any other standard ES5 way of loading a file
  • "module" - When a file is processed as an ES6 module

When using Babel 6 and babel-preset-es2015 (or Babel 5), Babel by default assumes that files it processes are ES6 modules. The thing that is causing you trouble is that in an ES6 module, this is undefined and files are all strict, whereas in the "script" case, this varies depending on the environment, like window in a browser script or exports in CommonJS code.

If you are using Babel, the easiest option is to write your code without the UMD wrapper, and then bundle your file using something like Browserify to automatically add the UMD wrapper for you. Babel also provides a babel-plugin-transform-es2015-modules-umd. Both are geared toward simplicity, so if you want a customized UMD approach, they may not be for you.

Alternatively, you would need to explicitly list all of the Babel plugins in babel-preset-es2015, making sure to exclude the module-processing babel-plugin-transform-es2015-modules-commonjs plugin. Note, this will also stop the automatic addition of use strict since that is part of the ES6 spec too, you may want to add back babel-plugin-transform-strict-mode to keep your code strict automatically.

As of babel-core@6.13 presets are able to take options, so you can also do

{
  "presets": [
    [ "es2015", { "modules": false } ]
  ]
}

in your Babel config (.babelrc) to use babel-preset-es2015 with module processing disabled.

这篇关于如何阻止 babel 将“this"转换为“undefined"(并插入“use strict")的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆