简体   繁体   English

如何阻止 babel 将“this”转换为“undefined”(并插入“use strict”)

[英]How to stop babel from transpiling 'this' to 'undefined' (and inserting "use strict")

EDIT : This is not about fat arrows .编辑:这不是关于胖箭头 It's also not about passing this to an IIFE .这也是不是通过一个IIFE。 It's a transpiler-related question.这是一个与转译器相关的问题。

So I've created a simple pub-sub for a little app I'm working on.所以我为我正在开发的一个小应用程序创建了一个简单的 pub-sub。 I wrote it in ES6 to use spread/rest and save some headaches.我在 ES6 中编写它以使用传播/休息并省去一些麻烦。 I set it up with npm and gulp to transpile it but it's driving me crazy.我用 npm 和 gulp 设置它来转译它,但它让我发疯。

I made it a browser library but realized it could be used anywhere so I decided to make it Commonjs and AMD compatible.我把它变成了一个浏览器库,但意识到它可以在任何地方使用,所以我决定让它兼容 Commonjs 和 AMD。

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?这可能与 Babel 不知道将是什么并将其转译有关,但是我可以采取任何其他方法吗?

UPDATE : Passing }((window || module || {}), function() { instead of this seems to work. I'm not sure this is the best approach though.更新:传递}((window || module || {}), function() {而不是这个似乎有效。不过我不确定这是最好的方法。

For Babel >= 7.x对于 Babel >= 7.x

ES6 code has two processing modes: ES6 代码有两种处理方式:

  • "script" - When you load a file via a <script> , or any other standard ES5 way of loading a file "script" - 当您通过<script>或任何其他标准 ES5 加载文件方式加载文件时
  • "module" - When a file is processed as an ES6 module "module" - 当文件作为 ES6 模块处理时

In Babel 7.x, files are parsed as "module" by default.在 Babel 7.x 中,文件默认被解析为“模块”。 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.给您带来麻烦的是,在 ES6 模块中, thisundefined ,而在"script"情况下,这取决于环境,例如浏览器脚本中的window或 CommonJS 代码中的exports Similarly, "module" files are automatically strict, so Babel will insert "use strict";同样, "module"文件自动严格,所以 Babel 会插入"use strict"; . .

In Babel 7, you'll need to tell Babel what type your file is if you want to avoid this behavior.在 Babel 7 中,如果你想避免这种行为,你需要告诉 Babel 你的文件是什么类型。 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.最简单的选择是使用"sourceType"选项在 Babel 选项中设置sourceType: "unambiguous" ,这实际上告诉 Babel 根据importexport语句的存在来猜测类型(脚本与模块)。 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.主要的缺点是,拥有一个不使用importexport的 ES6 模块在技术上没有问题,并且这些模块会被错误地视为脚本。 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, eg或者,您可以使用 Babel 7 的"overrides"选项将特定文件设置为脚本,例如

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

For Babel < 7.x对于 Babel < 7.x

ES6 code has two processing modes: ES6 代码有两种处理方式:

  • "script" - When you load a file via a <script> , or any other standard ES5 way of loading a file "script" - 当您通过<script>或任何其他标准 ES5 加载文件方式加载文件时
  • "module" - When a file is processed as an ES6 module "module" - 当文件作为 ES6 模块处理时

When using Babel 6 and babel-preset-es2015 (or Babel 5), Babel by default assumes that files it processes are ES6 modules.当使用 Babel 6 和babel-preset-es2015 (或 Babel 5)时,Babel 默认假设它处理的文件是 ES6 模块。 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.给您带来麻烦的是,在 ES6 模块中, thisundefined并且文件都是严格的,而在“脚本”情况下, this取决于环境,例如浏览器脚本中的window或 CommonJS 代码中的exports

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

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.或者,您需要在babel-preset-es2015 中明确列出所有 Babel 插件,确保排除模块处理babel-plugin-transform-es2015-modules-commonjs插件。 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.请注意,这也将停止自动添加use strict因为它也是 ES6 规范的一部分,您可能需要重新添加babel-plugin-transform-strict-mode以自动保持您的代码严格。

As of babel-core@6.13 presets are able to take options, so you can also dobabel-core@6.13预设可以选择选项,所以你也可以这样做

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

in your Babel config ( .babelrc ) to use babel-preset-es2015 with module processing disabled.在您的 Babel 配置 ( .babelrc ) 中使用babel-preset-es2015并禁用模块处理。

The "es2015" preset wraps the Babel output in a commonJs wrapper by default.默认情况下,“es2015”预设将 Babel 输出包装在 commonJs 包装器中。 Use the "babel-preset-es2015-script" (you must npm install --save babel-preset-es2015-script first) to output for "script" (no modules).使用“babel-preset-es2015-script”(你必须先npm install --save babel-preset-es2015-script )输出“script”(无模块)。 This was wreaking havoc on other libraries I was wrapping up using Babel.这对我使用 Babel 打包的其他库造成了严重破坏。

The preset: https://www.npmjs.com/package/babel-preset-es2015-script预设: https : //www.npmjs.com/package/babel-preset-es2015-script

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM