`export default XXX` 和`export { XXX as default }`的区别是什么?

1,012 阅读3分钟

在 JavaScript 的模块化开发中,export defaultexport { XXX as default } 是两种常见的导出方式,但它们之间的区别常常让开发者感到疑惑。本文将从语法、用途、实际案例和潜在问题几个方面来探讨这两种导出的差异,帮助你在项目中选择更适合的方式。

一、语法对比

  1. export default 的语法

    // 定义并导出默认值
    export default function sayHello() {
        console.log('Hello, World!');
    }
    
    // 或者直接导出一个变量
    export default 'Hello, World!';
    

    特点

    • 每个模块只能有一个默认导出。
    • 导出时无需指定名称,导入时可以随意命名。
    import greet from './module';
    greet(); // 输出: Hello, World!
    
  2. export { XXX as default } 的语法

    const sayHello = () => {
        console.log('Hello, World!');
    };
    
    // 使用命名导出,将其别名为 default
    export { sayHello as default };
    

    特点

    • 本质是命名导出的一种形式。
    • 导出时仍需要使用对象的解构形式进行映射。
    import greet from './module';
    greet(); // 输出: Hello, World!
    

二、用途与实际区别

1. 开发体验的差异

  • export default: 提供了模块的默认接口,适合导出一个模块的主要功能。例如,一个工具库的核心功能或一个类的默认实现。

    export default class Logger {
        log(message) {
            console.log(message);
        }
    }
    

    导入时:

    import Logger from './logger';
    const logger = new Logger();
    logger.log('Hello');
    
  • export { XXX as default }: 更适合在同一个文件中导出多个接口时,通过指定某个接口为默认值,提升代码可读性和维护性。

    const add = (a, b) => a + b;
    const subtract = (a, b) => a - b;
    
    export { add, subtract, add as default };
    

    导入时:

    import add, { subtract } from './math';
    console.log(add(1, 2)); // 输出: 3
    console.log(subtract(1, 2)); // 输出: -1
    

2. 工具链的支持差异

工具链(如 Webpack、Rollup)对 export defaultexport { XXX as default } 的处理是不同的:

  • export default: 默认导出在工具链中通常直接作为模块的主输出被处理,方便优化和 tree-shaking。

  • export { XXX as default }: 因为是命名导出的变体,其与普通命名导出共享同一个命名空间,可能会稍微增加解析的复杂性。

3. 命名与重构

  • export default: 重构或重命名默认导出的模块时,导入方的命名不会受到影响。

    export default function greet() {}
    

    即使导入方使用不同名称,也不会报错:

    import hello from './module';
    hello();
    
  • export { XXX as default }: 重命名或删除导出的接口可能影响所有导入方。

    export { greet as default };
    

    如果 greet 被重命名为 sayHello,需要同步更新:

    export { sayHello as default };
    

三、潜在问题与建议

  1. 避免误用默认导出

    默认导出虽然方便,但容易导致模块的用途模糊,特别是在多人协作的项目中。建议对工具库类项目尽量使用命名导出。

  2. 避免 export { XXX as default } 的滥用

    这种方式虽然灵活,但可能让代码的意图不够清晰。优先考虑直接使用 export default,除非需要在同一个文件中导出多个接口。

  3. 注意代码可读性

    对于复杂项目,命名导出(包括 export { XXX as default })能更好地描述模块内容,从而提升代码的可维护性。

四、总结

  • export default:适合单一主功能模块,导入时可随意命名,便于快速使用。
  • export { XXX as default }:适合导出多个功能时,明确指定主要功能为默认导出。

选择合适的导出方式,不仅能让代码更简洁,还能提升协作效率。如果你还在犹豫,可以记住一个简单的规则:如果模块的功能单一,直接使用 export default;如果模块提供多个功能,优先考虑命名导出,必要时使用 export { XXX as default }