纯HTML/CSS/原生JS简单项目是否需要使用import/export?
原生JS项目脚本引入方案选择与模块化问题解答
首先说你方法2报错的核心原因
你当前写的方法2属于错误的混用写法,根本不是标准的ES Module(即type="module")使用方式,出变量找不到的问题是必然的:
- 普通无
type="module"声明的script标签,顶层作用域直接指向全局window,所有顶层声明的变量、函数都会挂载到全局对象上,执行完全依赖你写的标签顺序,后面的文件可以直接访问前面文件声明的全局内容。 - 标记为
type="module"的脚本、以及被import关键字引入的JS文件,每个文件都拥有独立的模块作用域,顶层声明的变量不会自动挂载到window,只有显式用export导出的内容,才能被其他文件通过import获取;同时模块默认开启严格模式,未声明就赋值、隐式创建全局变量这类松散写法会直接抛错。
你现在的写法相当于既想在Main.js里通过import拿其他文件的函数,又没给对应文件加export导出,被import的文件里的变量全锁在自己的模块作用域里,自然会报未找到的错误。
正确使用import/export模块化的实际优势
如果完全按照ES Module规范写,你根本不需要在HTML里手动引入除入口文件外的其他JS,所有依赖关系都在JS代码里通过import声明,浏览器会自动按照依赖树顺序加载执行,不用你手动排标签顺序,核心优势很实在:
- 从根源解决全局变量污染:每个模块的变量都封闭在自身作用域内,不会出现多个文件同名变量互相覆盖的低级bug——比如两个文件都写了
let count = 0,全局脚本写法下后加载的文件会直接覆盖前一个的count值,模块化写法下两者完全互不干扰。 - 依赖关系清晰可追溯:哪个文件用了什么方法、方法来自哪个文件,直接看文件顶部的import列表就能理清楚,后期维护、删改代码的时候,不用翻遍所有文件找某个函数的定义位置,也不容易出现“删了个工具函数不知道哪个页面还在用”的问题。
- 原生支持懒加载:可以用
import('./xxx.js')的动态导入语法,在需要的时候(比如用户点击按钮、滚动到对应区域)才加载对应功能的JS,减少首屏需要加载的JS体积;如果是全局脚本写法,要实现同样的效果得自己手动动态插入script标签,还要处理加载时序、重复加载等问题,麻烦很多。 - 默认开启严格模式:会直接拦截很多JS松散语法导致的隐性bug,比如给未声明的变量赋值、顶层this默认指向window这类容易埋坑的写法,能帮你提前发现问题。
什么时候直接用顺序script标签引入就足够
不是所有小项目都必须硬上模块化,满足以下几个条件的话,直接用你说的方法1完全没问题,开发效率反而更高:
- 项目整体JS代码量很小,拆分后总共也就几百到一千多行,依赖关系非常简单
- 只有你一个人维护代码,对所有全局变量的命名、用途都很清楚,不会出现变量命名冲突
- 不需要做懒加载、代码分割这类性能优化,所有JS都要在首屏加载完成
- 没有跨页面复用代码模块的需求
小提示:哪怕用全局脚本顺序引入,也建议你把所有业务逻辑收敛到单个全局对象下,比如只在第一个脚本里声明
window.App = {},后续所有变量、函数都挂载到App对象上,不要直接在顶层声明一堆零散的全局变量,能少很多莫名其妙的变量覆盖bug。
如果要正确使用ES Module,参考写法
不要像你之前那样一半用全局脚本一半用模块,正确的写法非常简单:
- HTML里只保留一个入口脚本标签,不需要引入其他JS文件:
<script type="module" src="Main.js"></script>
- 所有拆分的JS文件里,需要给外部使用的函数、变量显式加
export声明,文件内部自用的变量不需要导出,不会暴露到外部:
// javascript2.js 示例 // 内部使用的配置,不会被外部访问到 const innerConfig = { pageSize: 10 } // 要给其他文件用的函数,显式导出 export function calcListTotal(list) { return list.reduce((sum, item) => sum + item.value, 0) }
- 在需要用到对应方法的文件(比如入口Main.js)里按需导入即可,不需要手动管理加载顺序,浏览器会自动处理依赖加载:
// Main.js 示例 import { calcListTotal } from './javascript2.js' import { formatTime } from './javascript3.js' // 直接使用导入的方法即可 const total = calcListTotal([{value: 1}, {value: 2}])
注意:ES Module需要运行在HTTP协议环境下,不能直接双击本地HTML文件通过file协议打开,否则会触发跨域报错,本地开发用任意静态服务启动即可,比如编辑器自带的本地预览服务、本地起个简单的静态文件服务都可以。
内容的提问来源于stack exchange,提问作者TomFan
相关产品推荐
相关产品推荐

