Q:大家通常会选择下面哪种方案,指点一下理由;方案三中普通和箭头哪个更好?
// 分别导出
export function funA(){}
export function funB(){}
export function funC(){}
...
// 分别导入(按需)
import {funA,funB,...} from 'XX'
// 分别导出 + 默认导出
export function funA(){}
export function funB(){}
export function funC(){}
...
export default { funA,funB,funC }
// 可默认全部导入也可按需导入
import {funA,funB} from 'XX'
或
import Api from 'xx'
Api.funA...
// 直接默认导出全部
export default {
// 普通好?
funA(){},
// 箭头好?
funB: () => {}
}
// 默认导入
import Api from 'XXX'
1
webszy 279 天前
方案 1 ,方便 tree-shaking
|
3
tlerbao OP @webszy #2 咱就是说假设 default 有 5 个接口,那么 import default 和只导入其中两个最后在打包体积上能差多啥哈哈。是不是中小项目完全不用考虑这个。
|
4
codehz 279 天前
不是可以 import * as Api from 'XXX' 吗
|
6
kneo 279 天前 via Android
看具体情况。细粒度的函数肯定是一二。复杂点的业务有时候也用得着三。关键还是看实际怎么用的。要是用的别扭就再琢磨琢磨。
|
7
XCFOX 279 天前
几乎不用 export default ,因为 export default 不方便配合桶文件使用
|
9
IvanLi127 279 天前
从编码风格上来说,我选方案一,它看起来直观。方案二写起来怕漏掉,方案三缩进太多。
|
11
tlerbao OP @webszy #5 方案一你说换成箭头更好但是在 Webstorm 下,箭头函数没有类型注解,不如普通 function 来的直观
不知道你能不能看见图,红线标注的普通函数默认有类型注解,不用悬停鼠标就知道返回什么类型哈 |
13
XCFOX 279 天前
桶文件本身不提供任何实现,而是重新导出其他模块的导出,一个典型的桶文件是: https://github.com/microsoft/TypeChat/blob/main/src/index.ts
重新导出语句 export * from 'xxx' 是无法导出 export default 的。 假如你有这样的文件结构: src/ |-- utils/ | |-- format.ts | |-- validate.ts | |-- index.ts 并且在 src/utils/format 中使用 export default , 那么始终得使用 import '../utils/format' 导入。 但是如果你使用桶文件,通常只需要 import '../utils' |
14
rabbbit 279 天前
const funA = () => {}
export {funA} import {funA} from "xxx" |
20
XCFOX 279 天前
@tlerbao 使用 vite 的话,在 dev 模式下不会自动 tree shaking ,但在 build 时会 tree shaking ,使用 webpack 始终会自动 tree shaking
|
21
tlerbao OP @XCFOX #20 假设 import '../utils' 导入了 format.ts 的全部和 validate.ts 的全部,您的意思,假设我代码中只调用了 format 和 validate 中的部分,那么 vite 在打包的时候会自动 tree shaking ?是这个意思吗?
|
22
lyxxxh2 279 天前
几个接口 直接写
十几个接口 方案 3 二十几个接口 方案 1 方案 2: 感觉有点无语 1 和 3 的缝合怪 |
23
CLMan 279 天前 2
这个可以参考 google typescript style guidle ,只需要使用 1 ,不建议使用 2,3 ,也没有什么必须使用 2,3 的场景。
至于上面说的桶文件,其实更多是基于兼容性和习惯( Deno 作者吐槽为设计错误),并不是说这种设计就是好的。通常情况下,仅限于包级别使用( src/index.js )。 如果考虑浏览器兼容,需要 iife 模式(脚本模式),rollup 对 1,2 产生相同的结果,因此也不需要必须使用默认导出。 我也不知道当初 es 是为啥设计默认导出,我一直以来猜测是为了兼容 iife 模式,一个库提供一个全局对象,避免污染 global 作用域。但没有证据能证明我的猜测。 |
24
CLMan 279 天前 1
@CLMan 我翻了下 ECMAScript 的早期相关讨论,终于找到了一个相关文档: https://archives.ecma-international.org/2014/misc/2014misc6.html 。
这个文档证明了我的以上猜测,默认导出设计的初衷就是为了兼容类似 jQuery 这样 ES6 之前的流行的 JS 使用模式(全局单例对象),也确实如文档所说,给当时的 JS 使用者以及后来的 JS/TS 使用者造成了混乱。 这是典型的编程语言设计时因缺乏长远考虑,给后来的使用者带来困扰,后来的使用者还必须得考古才能理解其应用场景,了解语言的缺陷仅为了避免使用该缺陷是当代的编程语言学习者常常面临的情况。 |
26
SchneeHertz 279 天前
function funA(){}
function funB(){} function funC(){} ... export default { funA,funB,funC } import {funA,funB} from 'XX' // or import XX from 'XX' 只是习惯 |
27
mark2025 279 天前
1. 尽量避免同时使用具名导出和默认导出
2. 推荐统一使用具名导出 |