ES6 --- import/export 全解析

前言:在现代前端开发中,模块化开发是不可或缺的核心能力,ES6 引入的 importexport 语法,彻底解决了传统 JS 全局变量污染、依赖管理混乱的问题,为工程化开发奠定了基础。本文将详细讲解导入导出的所有常用用法,搭配可直接复制运行的 Demo,覆盖基础用法、进阶技巧和常见场景,新手也能快速上手。

提示:ES6 模块需在 <script type="module"> 标签中使用,或在 Vue、React、Vite 等工程化项目中直接使用(无需额外配置);浏览器原生使用时,导入路径需包含 .js扩展名,构建工具中可省略。

一、核心概念:导出(export)------向外暴露模块接口

导出的核心作用是将当前模块(一个 JS 文件即为一个模块)中的变量、函数、类等内容暴露出去,供其他模块导入使用。ES6 导出分为具名导出默认导出 两种方式,可单独使用,也可混合使用。

1. 具名导出(Named Export)

具名导出是最常用的方式,支持同时导出多个成员,导出时需指定明确的名称,导入时必须使用对应的名称(可重命名)。

特点:可多次使用 export 语句,导入时需用大括号 {} 包裹,名称必须与导出时一致(除非使用 as 重命名)。

Demo 1:具名导出的两种写法

新建 utils.js(导出方):

javascript 复制代码
// 写法1:直接在声明时导出(推荐,简洁直观) 
export const PI = 3.14159; 
export function add() {} 
export class Calculator { multiply() {} } 

// 写法2:先声明,再集中导出(适合批量导出,清晰可控) 
const subtract = () => {}; 
const divide = () => {}; 
export { subtract, divide }; // 用大括号包裹多个具名成员 

// 进阶:具名导出重命名(解决名称冲突问题) 
export { divide as safeDivide }; // 将 divide 重命名为 safeDivide 导出

2. 默认导出(Default Export)

默认导出用于导出模块的"主成员",一个模块 只能有一个默认导出,导入时可自定义名称,无需使用大括号。

特点:语法简洁,适合导出单个核心功能(如一个组件、一个主函数),导入时名称可自由定义,无需与导出时一致。

Demo 2:默认导出的三种写法

新建main.js(导出方):

javascript 复制代码
// 写法1:导出匿名函数(最简洁,适合导出单个函数) 
export default function(a, b) { return a + b; } 

// 写法2:导出已声明的变量/函数(推荐,可读性更强) 
const sayHello = (name) => `Hello, ${name}!`; 
export default sayHello; 

// 写法3:导出类(适合组件、工具类场景) 
class User { 
    constructor(name, age) { 
        this.name = name; this.age = age; 
    } 
    showInfo() { 
        console.log(`姓名:${this.name},年龄:${this.age}`); 
    } 
} 
export default User;

3. 混合导出(具名 + 默认)

一个模块可同时存在一个默认导出和多个具名导出,是实际开发中最常用的场景(如导出一个主组件 + 多个辅助工具)。

Demo 3:混合导出示例

新建 mixExport.js(导出方):

二、核心用法:导入(import)------引入其他模块的接口

导入的核心作用是获取其他模块导出的成员,根据导出方式的不同,导入语法也有所区别。下面对应导出方式,讲解所有导入用法,搭配完整 Demo。

1. 导入具名导出的成员

对应具名导出,导入时需用大括号 {} 包裹成员名称,名称必须与导出时一致,可单独导入、批量导入,也可重命名导入。

Demo 4:具名导入的几种用法

新建 importNamed.js(导入方),导入上面 utils.js 中的具名成员:

javascript 复制代码
// 1. 批量导入:导入指定的多个具名成员(推荐) 
import { PI, add, Calculator } from './utils.js'; 
// 使用导入的成员 
console.log(PI); // 3.14159 
console.log(add(2, 3)); // 5 
const calc = new Calculator(); console.log(calc.multiply(2, 3)); // 6 

// 2. 单独导入:只导入需要的成员(按需导入,支持Tree-shaking) 
import { subtract } from './utils.js'; 
console.log(subtract(5, 2)); // 3 

// 3. 重命名导入:解决名称冲突(关键技巧) 
import { divide as safeDivide, safeDivide as divide } from './utils.js'; console.log(safeDivide(6, 2)); // 3 
console.log(divide(6, 2)); // 3(重命名后可自定义使用名称) 

// 4. 整体导入:将所有具名成员导入为一个对象(不常用,适合批量使用多个成员) 
import * as utils from './utils.js'; 
console.log(utils.PI); // 3.14159 
console.log(utils.add(2, 3)); // 5 
console.log(utils.subtract(5, 2)); // 3

2. 导入默认导出的成员

对应默认导出,导入时无需大括号,可自定义成员名称(无需与导出时一致),这是默认导出的核心优势。

Demo 5:默认导入的用法

新建 importDefault.js(导入方),导入上面 main.js 中的默认成员:

javascript 复制代码
// 写法1:自定义名称导入(推荐,根据业务场景命名) 
import myAdd from './main.js'; // 导出的是add函数,导入时命名为myAdd console.log(myAdd(2, 3)); // 5 

// 写法2:使用任意名称(灵活,适合简单场景) 
import hello from './main.js'; // 导出的是sayHello函数,导入时命名为hello console.log(hello('ES6')); // Hello, ES6! 

// 写法3:导入默认导出的类 
import UserInfo from './main.js'; // 导出的是User类,导入时命名为UserInfo 
const user = new UserInfo('张三', 20); user.showInfo(); // 姓名:张三,年龄:20

3. 混合导入(默认 + 具名)

对应混合导出,导入时需先写默认导出的名称,再用大括号包裹具名成员,是实际开发中最常用的导入方式。

Demo 6:混合导入示例

新建 importMix.js(导入方),导入上面 mixExport.js 中的成员:

javascript 复制代码
// 混合导入语法:默认成员在前,具名成员在后(顺序固定) 
import mainFn, { msg, helperFn1, helperFn2 } from './mixExport.js'; // 使用导入的成员 mainFn(); // 这是默认导出的主函数 
console.log(msg); // Hello ES6 Module helperFn1(); helperFn2(); 

// 进阶:混合导入 + 重命名 
import myMainFn, { msg as tip, helperFn1 as fn1 } from './mixExport.js'; myMainFn(); // 这是默认导出的主函数 console.log(tip); // Hello ES6 Module fn1();

4. 特殊导入:仅执行模块(无绑定)

有些模块无需导入任何成员,仅需执行其内部代码(如初始化配置、埋点脚本、全局样式等),此时可使用无绑定导入。

Demo 7:无绑定导入示例
javascript 复制代码
// 仅执行模块内部代码,不导入任何成员 import './init.js'; // init.js 中可能是初始化全局配置、埋点等代码

三、进阶技巧与注意事项

1. 动态导入(Dynamic Import)

ES6 支持动态导入,通过 import() 函数实现,返回一个 Promise,适合按需加载、条件加载(如路由懒加载、组件懒加载),解决首屏加载体积过大的问题。

javascript 复制代码
// 动态导入示例(按需加载utils模块) 
button.addEventListener('click', async () => { 
   // 动态导入,返回Promise,需用async/await或.then()处理 
    const utils = await import('./utils.js'); 
    console.log(utils.add(2, 3)); // 5 
    console.log(utils.PI); // 3.14159 }); // 条件加载示例 
    if (isNeedCalculator) { 
        import('./utils.js').then(({ Calculator }) => { 
            const calc = new Calculator(); 
            console.log(calc.multiply(2, 3)); // 6 }); 
     })
    }
})

2. 实时绑定特性

具名导出是"实时绑定"(引用),而非值拷贝,若导出模块中的成员发生变化,导入方获取到的值也会同步更新;默认导出是值拷贝(除非导出的是引用类型,如对象、数组)。

javascript 复制代码
// 导出方:counter.js 
export let count = 0; 
export function increment() { count++; } 

// 导入方:useCounter.js 
import { count, increment } from './counter.js'; 
console.log(count); // 0 
increment(); // 调用导出方的函数,修改
count console.log(count); // 1(同步更新,实时绑定)

3. 常见注意事项(避坑重点)

  • 一个模块 只能有一个默认导出,但可以有多个具名导出,重复默认导出会报错。

  • 具名导入/导出的名称必须一致(大小写敏感),否则会导入失败(undefined),可通过 as 重命名解决。

  • importexport 必须在模块顶层作用域,不能在函数、if 条件语句中使用(静态解析特性),如需动态加载,使用动态导入 import()

  • 浏览器原生使用时,导入路径必须包含 .js 扩展名(如 ./utils.js),不能省略;构建工具(Vite、Webpack)中可省略。

  • 导入的成员是只读的,不能修改(如 PI = 3.14 会报错),避免破坏模块封装性。

四、完整可运行示例(整合所有用法)

下面提供一套完整的 Demo,包含导出方和导入方,复制到本地即可运行(需用浏览器打开,或在工程化项目中使用)。

1. 导出方:completeExport.js

javascript 复制代码
// 1. 具名导出 
export const name = 'ES6 模块'; 
export function sum(a, b) { return a + b; } 
export const tools = { 
    log: (msg) => console.log(`[日志]:${msg}`), 
    alert: (msg) => console.warn(`[警告]:${msg}`) 
}; 

// 2. 具名导出重命名 
const deleteData = (id) => console.log(`删除数据:${id}`); 
export { deleteData as removeData }; 

// 3. 默认导出(主功能) 
export default function main() { console.log('=== 完整模块演示 ==='); }

2. 导入方:completeImport.js

javascript 复制代码
// 混合导入(默认 + 具名) 
import main, { name, sum, tools, removeData } from './completeExport.js'; 

// 执行默认导出的主函数 
main();

 // 使用具名导出的成员 
console.log('模块名称:', name); // 模块名称:ES6 模块 
console.log('2 + 3 =', sum(2, 3)); // 2 + 3 = 5 
tools.log('导入导出演示成功'); // [日志]:导入导出演示成功 tools.alert('注意:导入的成员不可修改'); // [警告]:注意:导入的成员不可修改 removeData(1001); // 删除数据:1001 

// 动态导入示例 
setTimeout(async () => { console.log('\n=== 动态导入演示 ==='); 
const module = await import('./completeExport.js'); 
console.log(module.name); // ES6 模块 
console.log(module.sum(3, 4)); // 7 
}, 1000);

3. 运行方式

新建 index.html,引入导入方文件,添加 type="module" 属性:

javascript 复制代码
<!DOCTYPE html> ES6 导入导出演示

用浏览器打开 index.html,打开开发者工具(F12),在 Console 面板即可看到运行结果。

五、总结

ES6 导入导出的核心是"模块化隔离"和"显式依赖",掌握以下关键点,就能应对所有开发场景:

  1. 导出分两种:具名导出(多个,需匹配名称)、默认导出(1个,可自定义名称),支持混合导出。

  2. 导入对应两种:具名导入(用 {},名称匹配)、默认导入(无 {},名称自定义),混合导入需先默认后具名。

  3. 进阶技巧:重命名(as)、动态导入(import())、实时绑定,避坑重点是顶层作用域、路径规范和只读特性。

模块化是现代前端的基础,熟练掌握 importexport,能让你的代码更具可维护性、可复用性,为后续学习工程化工具(Vite、Webpack)打下坚实基础。

如果觉得有用,欢迎点赞收藏,如有疑问或补充,评论区留言交流

相关推荐
SLD_Allen3 小时前
Go语言runtime全景
开发语言·javascript·golang
Elastic 中国社区官方博客3 小时前
OpenTelemetry Java 扩展:无需分叉 agent 即可自定义追踪
java·大数据·运维·开发语言·数据库·人工智能·elasticsearch
计算机魔术师3 小时前
NVIDIA 季度营收指引达 1080 亿美元,首次突破单季千亿大关
前端
不灭的黄金瞳1233 小时前
C语言手写顺序表
c语言·开发语言·数据结构
阿无,3 小时前
Java多线程面试题之AQS
java·开发语言
数据狐(Datafox)3 小时前
京东商品列表API技术解析与落地应用(含标准 JSON 示例)
java·大数据·前端·人工智能·python·数据分析·json
风萧何3 小时前
架构艺术,是权衡的艺术。
前端·javascript·架构
偷偷挖矿的牛马矿工3 小时前
execa NodeJs新一代child_process的强力替代品
javascript
豆沙沙包?3 小时前
C++~~~set容器、map容器(p57-P69)
开发语言·c++