javascript - 在 Node 中使用 Babel 导入 vs 要求

标签 javascript node.js ecmascript-6 babeljs

这个问题在这里已经有了答案:





Can't require() default export value in Babel 6.x

(3 个回答)


5年前关闭。




我想在一个文件中导入一个类:

"use strict";
import models from "../model";
class Foo {
    bar() {
    }
}
export default new Foo();

它在我使用导入时起作用,例如:
import Foo from "./foo";
console.log(Foo.bar); // [Function bar]

问题是用 require 来做这件事给了我未定义的:
var Foo = require("./foo");
console.log(Foo.bar); // undefined

Foo 变量似乎是一个空类。为什么呢?这是怎么回事?

最佳答案

TL;博士
这是因为使用 import 导入不同于 require 。当您使用语法 import X from "Y" 导入模块时,会自动导入默认导出,因为该语法旨在按规范导入默认导出。但是,当您 require 时,默认导出不会像您期望的那样自动导入。您必须添加 .default 才能使用 require 获得默认导出,例如: require("./foo").default
通天塔转译
看看 Babel transpiles 的一些示例代码如何:

export { x }
变成:
"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.x = x;
这是有道理的,因为 x 只是正常导出。然后你会继续做:
require("module").x;
接收 x 。同样,尝试以下操作:
export default new Foo();
那变成:
"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = new Foo();
您会看到默认导出作为名为 exports 的属性附加到 default 对象,就像使用属性 x 导出 x 一样。这意味着,要使用 require 获得默认导出,您需要执行以下操作:
require("module").default;
现在解释为什么它是 undefined 。在行中:
var Foo = require("./foo");
这里的 Foo 实际上只是一个具有 default 属性的对象:
{
    default: //Whatever was exported as default
}
因此,尝试执行 Foo.bar 将产生 undefined 因为没有 bar 属性。您需要访问 default 属性才能访问您的实例。
您可能会认为这有点笨拙,其他人也一样。这就是为什么 there's a plugin 摆脱对额外 .default 的需要的原因。该插件执行 module.exports = exports["default"] 将 ES5 中的 module.exports 分配给 exports["default"] .1importrequire 之间的区别
对于 import 语法,Babel 进行以下转译:
import Foo from "./foo";
Foo.bar();
变成:
"use strict";

var _foo = require("./foo");

var _foo2 = _interopRequireDefault(_foo);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

_foo2.default.bar();
为了逐行分解,Babel 只是 require s 模块。然后,它在模块上调用 _interopRequireDefault。使用 obj && obj.__esModule 进行检查以确保模块实际导出任何内容并且模块以 ES2015/ES6 语法导出。如果是,则按原样返回模块,否则返回 { default: obj }。这是为了确保 ES5 中的 module.exports = x 被视为与 ES2015/ES6 中的 export default x 相同。你会注意到对于默认的导入语法,Babel 会自动添加 .default 来检索默认导出。
但是,对应的代码为 require :
var Foo = require("./foo");
Foo.bar();
是完全有效的 ES5 代码,所以没有任何东西被转译。因此,.default 在使用时永远不会添加到 Foo 中。因此,不会检索默认导出。

笔记
1需要注意的是,module.exportsexports只是指同一个对象,见this answermodule.exports 保存从模块导出的数据。 module.exports = x 成功导出 x 作为默认值并且不需要 .default 上的额外 require 的原因是因为您将 module.exports 分配给一件事。由于 module.exports 包含导入的数据,因此 require("module") 导入 module.exports 是什么,即 x 。如果 module.exports 是 3,那么 require("module") 就是 3。如果 module.exports 是像 { blah: "foo" } 这样的对象,那么 require("module") 就是 { blah: "foo" }。默认情况下,modulemodule.exports 是对象。
另一方面, exports.default 导出一个具有 module.exports 属性的对象(即与 default 相同的对象),该属性包含默认导出。您可能想要执行 exports = x 以将 x 作为默认值导出,但由于 exports 被分配了对 module.exports 的引用,这将破坏引用并且 exports 将不再指向 module.exports

关于javascript - 在 Node 中使用 Babel 导入 vs 要求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42475691/

相关文章:

javascript - 将用户的正则表达式结果大写

javascript - 在回调方法中传递动态值

node.js - Socket.io+SailsJS : Chat application-How to check whether the client is shut down, 并使用户离线?

javascript - 如何浏览、编译 ES6 和缩小 NodeJS 应用程序

javascript - 使用 ES6 解构简化 javascript 对象的创建

javascript - 使用 jQuery 更改所有外部链接

javascript - 如何在 Angular 中向原生元素添加多种样式

javascript - 我的 JQuery 函数出了什么问题?

javascript - 使用 Node 显示 SQL 值

javascript - 用数组元素替换字符串