ES6模块:导出单个静态方法类或多个单独的方法。

71

我正在使用ECMAScript6模块。以下选项中正确的从模块导出/导入多个方法的方式是什么?

静态方法的单个类:

//------ myClass.js ------

export default class myClass {

  static myMethod1() {
    console.log('foo'); 
  }

  static myMethod2(args...) {
    console.log('bar'); 
  }  

}

//------ app.js ------

import myClass from 'myClass';
myClass.myMethod1();    //foo

多个导出方法:

//------ myMethods.js ------

export function myMethod1() {
    console.log('foo');
}

export function myMethod2() {
    console.log('bar');
}

//------ app.js ------
import {myMethod1, myMethod2} from 'myMethods';
myMethod1()    //foo;


//OR
import * as myMethods from 'myMethods';
myMethods.myMethod1()    //foo;

1) 导出: 仅包含静态方法的类感觉有点“代码异味”,但是单独导出每个方法也有些啰嗦。这只是开发者偏好,还是存在性能影响?

2) 导入: 我更喜欢使用“* as”语法,因为它允许您使用点表示法(引用模块和方法),增加代码可读性。但当我可能只使用其中1种方法时,是否会有性能方面的影响?


使用 import {myMethod1, myMethod2} from 'myMethods'; 导入的方法不需要像变量一样进行解引用。虽然说,我不确定点符号是否实际上被视为变量。 - user5321531
2个回答

64

仅有静态方法的类会让人感到有些“代码异味”

确实如此。在这里你不需要一个class结构!只需导出一个普通的“模块”对象:

//------ myMethods.js ------

export default {
  myMethod1() {
    console.log('foo'); 
  },
  myMethod2(args...) {
    console.log('bar'); 
  }  
};

尽管如此,我建议您采用多个导出的第二种方法。

逐个导出每个东西确实有些啰嗦

好吧,您不需要任何包装结构,所以我认为它的样板更少。您只需要明确标记要导出的所有内容,这并不是坏事。

* as语法是我首选的方法,因为它允许您使用点符号表示法(引用模块和方法),从而帮助代码可读性。

这在很大程度上取决于您所编写的代码类型;有时简洁性优越,但显式引用模块的能力也很有帮助。请注意,使用* as的命名空间导入和默认导入对象非常相似,但只有命名导出才允许您通过import {myMethod1, myMethod2}直接引用它们。因此最好将选择权留给导入您模块的人。

这会有任何性能影响吗?

不会太多。当前的ES6实现也没有旨在进行性能优化。

通常情况下,静态标识符比属性访问更容易解析和优化[1],多个命名导出和部分导入在理论上可能会使JIT更快,当捆绑时删除未使用的导出可以减小文件大小。有关详细信息,请参见此处。几乎不会有明显的性能差异,您应该使用更易于维护的方法。

[1]: 模块命名空间(import * as ns)也是静态的,即使ns.…看起来像动态属性访问


如果要导出一个类以便实例化类的实例,我会使用一个类。否则,只需要一个简单的 { ... } 就足够了。 - user5321531
1
@user5321531:是的,但只有静态方法的类不需要实例化 :-) - Bergi
@Rivenfall 你可以像这样自己导入:import * as namespace from './myself';, 然后 export { namespace as default }。不过我建议避免这样做,让库的使用者自己导入命名空间即可。 - Bergi
2
@StevenT.Cramer 好的,你总是可以使用 import { default as somethingcreative } from 'foo'/import somethingcreative from 'foo' 的方式进行导入,命名导出并不会改变这一点。当然,惯例是将 "foo" 模块作为 foo 导入。如果你的开发人员不想遵循这个惯例,那就是他们的问题(或者他们有一个好的理由)。 - Bergi
1
@chkpnt 许多测试库都支持模拟 ES 模块(例如testdoubleesmockjest)。 - Bergi
显示剩余4条评论

6
TLDR; 使用多个导出方法和显式导入。
@Bergi在第一种情况下正确地指出不需要具有静态字段的类,只需要一个对象。然而,这个选项被Axel Rauschmayer不鼓励使用:

请注意,默认导出对象通常是反模式(如果您想导出属性)。您会失去一些ES6模块的好处(tree-shaking更快的导入访问)。

Airbnb的开发人员建议使用命名导出和显式通配符导入,请参见此线程:https://github.com/airbnb/javascript/issues/710#issuecomment-297840604

1
在许多情况下,可读性比树摇更重要。 - Michael Freidgeim
1
@MichaelFreidgeim 有很多提高可读性的方法,而不需要打破合理的约定。不打破它们也可以节省很多精力,除非你最喜欢的消遣是思考摇树的成本效益。 :) - thisismydesign

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接