use*_*999 4 javascript node.js ecmascript-6 babeljs
我想在一个文件中导入一个类:
"use strict";
import models from "../model";
class Foo {
bar() {
}
}
export default new Foo();
Run Code Online (Sandbox Code Playgroud)
它在我使用import时有效,例如:
import Foo from "./foo";
console.log(Foo.bar); // [Function bar]
Run Code Online (Sandbox Code Playgroud)
问题是,使用require执行它会给我未定义:
var Foo = require("./foo");
console.log(Foo.bar); // undefined
Run Code Online (Sandbox Code Playgroud)
而Foo变量似乎是一个空类.为什么会这样?这是怎么回事?
这是因为导入与import不同require.使用语法导入模块时import X from "Y",会自动导入默认导出,因为语法是按规范导入默认导出.但是,当您使用时require,默认导出不会像您期望的那样自动导入.您必须添加.default以获取默认导出,require如:require("./foo").default.
export { x }
Run Code Online (Sandbox Code Playgroud)
变为:
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.x = x;
Run Code Online (Sandbox Code Playgroud)
这很有道理,因为x它只是正常导出.然后你会继续做:
require("module").x;
Run Code Online (Sandbox Code Playgroud)
收到x.同样,请尝试以下操作:
export default new Foo();
Run Code Online (Sandbox Code Playgroud)
那就变成:
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = new Foo();
Run Code Online (Sandbox Code Playgroud)
您将看到默认导出exports作为名为的属性附加到对象default,就像x使用property导出一样x.这意味着,要获得默认导出require,您需要执行以下操作:
require("module").default;
Run Code Online (Sandbox Code Playgroud)
现在来解释一下它的原因undefined.在线:
var Foo = require("./foo");
Run Code Online (Sandbox Code Playgroud)
Foo这里实际上只是一个具有default属性的对象:
{
default: //Whatever was exported as default
}
Run Code Online (Sandbox Code Playgroud)
因此,尝试做Foo.bar会产生undefined因为没有bar财产.您需要访问该default属性才能访问您的实例.
你可能会认为这有点笨重,其他人也这样做.这就是为什么有一个插件来摆脱额外的需要.default.该插件module.exports = exports["default"]用于将module.exportsES5 分配给exports["default"].1
import和之间的区别require对于import语法,Babel执行以下转换:
import Foo from "./foo";
Foo.bar();
Run Code Online (Sandbox Code Playgroud)
变为:
"use strict";
var _foo = require("./foo");
var _foo2 = _interopRequireDefault(_foo);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
_foo2.default.bar();
Run Code Online (Sandbox Code Playgroud)
为了逐行分解,巴贝尔只是require模块.然后,它调用_interopRequireDefault模块.进行检查obj && obj.__esModule以确保模块实际导出任何内容,并使用ES2015/ES6语法导出模块.如果是,则按原样返回模块,否则{ default: obj }返回.这是为了确保module.exports = x在ES5中处理与export default xES2015/ES6中相同的处理.您会注意到,对于默认导入语法,Babel会自动添加.default以检索默认导出.
但是,相应的代码有require:
var Foo = require("./foo");
Foo.bar();
Run Code Online (Sandbox Code Playgroud)
是完全有效的ES5代码,所以没有任何内容被编译.因此,在使用时.default永远不会添加Foo.因此,不会检索默认导出.
1应该注意的是module.exports,exports只是引用同一个对象,请参阅此答案.module.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" }.默认情况下,module和module.exports是对象.
另一方面,使用保存默认导出的属性导出exports.default对象(与同一对象引用module.exports)default.您可能希望exports = x导出x为默认值,但由于exports分配了module.exports对此的引用exports将导致引用中断,并且将不再指向module.exports.
| 归档时间: |
|
| 查看次数: |
690 次 |
| 最近记录: |