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)打下坚实基础。

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

相关推荐
小杍随笔1 小时前
【iNovel 前端架构深度解析:基于 Vue 3 + TypeScript + Tauri 的跨端小说写作工具】
前端·架构·typescript
yqcoder1 小时前
JavaScript 异步基石:Promise 完全指南
开发语言·前端·javascript
wangl_921 小时前
初探 C# 15 的 Union Types
java·开发语言·算法·c#·.net·.net core
深度先生1 小时前
Windows 踩坑实录:better-sqlite3 安装、编译、打包报错彻底解决
前端
胡志辉1 小时前
Nginx CVE‑2026‑42945:隐藏18年高危漏洞被曝光(附解决方案)
前端·后端·nginx
代码煮茶1 小时前
Vue3 上传组件实战 | 从 0 封装大文件分片上传组件(断点续传 / 秒传 / 进度条)
javascript·vue.js
Csvn1 小时前
Vue 性能优化实战指南
前端·vue.js
故事和你911 小时前
洛谷-【图论2-1】树2
开发语言·数据结构·c++·算法·动态规划·图论
折哥的程序人生 · 物流技术专研1 小时前
Java面试85题图解版 · 全系列总目录
java·开发语言·后端·面试·职场和发展