使用模块导出时,为什么导出实例而不是类本身? (如何导出构造函数)

时间:2016-06-01 05:29:08

标签: javascript ecmascript-6

我有一个包含以下内容的文件:

rune

在另一个文件中,我可以像这样导入它:

var Foo = function() {};
Foo.prototype.bar = function() { return "hello world" }
export default function() {
  return new Foo();
}

我需要一段时间才能完成这项工作。我感到困惑的具体事情是import Foo from "./my_other_file.js"; var foo = new Foo(); console.log(foo.bar()); // => "hello world" 。我最初的倾向是export default function() { return new Foo() }(换句话说,返回类本身而不是实例)。

必须初始化类两次(导出时一次,导入后一次)似乎是多余的。这不是我第一次遇到这类事情 - 我在使用继承时也看到了它。

我的问题是 - 为什么会这样?这对我来说似乎不直观,所以我希望它有充分的理由。

3 个答案:

答案 0 :(得分:2)

  

为什么会这样?

模块不直接导出Foo构造函数,而只导出创建新Foo实例的工厂函数。请注意,它不会导出实例本身(正如您的问题标题所示)。

这样做的好处是您可以省略new关键字并执行

import Foo from "./my_other_file.js";
var foo = Foo(); // <==
console.log(foo.bar());

缺点当然是你不能轻易地对类进行子类化或扩展。

  

我最初的倾向是return Foo

不,您不应导出返回类的函数(构造函数)。您应该使用export {Foo as default}

直接导出类本身
export default function Foo() {};
Foo.prototype.bar = function() { return "hello world" };

(当然,还是ES6中的export default class Foo {…})。

答案 1 :(得分:1)

我经常查看我将我的EMCAScript6类定义为类似C#Api中的类文件的文件。

在你的情况下,你要在Foo-Class文件中这样做,来定义你的类:

export default class Foo {
    bar() {
        return "hello world"
    }
}

另一个文件保持不变。

这样您就不必创建该类的两个实例。您只需要创建使用它的实例。

如果您只是希望Foo文件返回一个返回&#34; hello world&#34;的函数,那么您可以这样做

export default function() {
    return "hello world";
}

然后像其他函数一样在其他文件中使用Foo。

答案 2 :(得分:1)

上面的代码段预先假定有一个导入器(例如框架应用程序)需要工厂函数而不是构造函数:

import fooFactory from from "./my_other_file.js";

// launches a function and throws on constructors
fooConsumer(fooFactory);

任何方式,保持default(作为手头的出口)和命名出口始终是个好主意。

export var Foo = function() {};
Foo.prototype.bar = function() { return "hello world" }
export default function() {
  return new Foo();
}

即使现在没有在应用程序中使用已命名的导出,它们也可能在以后有用(用于测试)。