动态加载脚本时,函数表达式堪称最得力工具之一——它能实现延迟执行、避免全局污染、封装依赖逻辑,还能配合 Promise 或回调在异步加载完成后安全调用。简而言之,就是让代码在正确的时机与作用域内执行,避免产生干扰。

不过,仅掌握概念还不够。实际开发中,有几个关键点需要精准把握。
确保脚本加载完成后再执行函数
动态插入的 标签默认采用异步加载方式,浏览器不会等待它下载完毕再继续后续逻辑。若直接调用脚本内部定义的函数,通常会遇到 undefined 的报错。如何解决?
- 监听
script.onload事件,待脚本下载并执行完成后,再触发函数表达式。这是最直接的方案。 - 将业务逻辑封装为具名或匿名的函数表达式,放入
onload回调中调用。这样脚本内的内容不会提前暴露到全局,干净利落。 - 举例说明:加载完
lodash.js后,可编写const init = () => _.throttle(...); init();——注意,只有脚本完全就绪,该箭头函数才会被调用执行。
利用 IIFE 隔离作用域与进行依赖检查
有时脚本加载完成后,需要确认它是否成功注入了(例如第三方库是否挂载到 window 上)。此时立即执行函数表达式(IIFE)便派上用场——轻量、自包含,适合执行一次性检测与初始化。
(function() { if (typeof $ !== 'undefined') { /* jQuery 已就绪 */ } })();这种写法既不会污染全局,又能快速判断依赖是否到位。- 为避免重复执行,可在 IIFE 内部设置标志位,例如
window._loaded_jquery = true,下次加载时直接跳过。 - 在多脚本并行加载的场景中,每个脚本加载完毕各自运行一段独立的检查逻辑,IIFE 是最省事的方案。
结合 Promise 实现链式加载与错误处理
若使用回调嵌套处理多个脚本的加载顺序,代码很快会演变为“圣诞树”结构。更优的选择是 Promise——将函数表达式嵌入 then 中,整个流程变得清晰可控。
- 封装一个
loadScript(src)函数,返回Promise。脚本加载成功时resolve,失败时reject,随后在then中传入函数表达式来处理结果。 - 利用
catch捕获加载失败的情况,执行降级函数——比如更换 CDN 备份,或启用本地polyfill。这样即使主源出现异常,功能仍能兜底。 - 如需同时加载多个脚本,使用
Promise.all([loadScript(a), loadScript(b)])并行拉取,待所有脚本就绪后,在then中组合函数表达式进行后续处理。效率和可读性双赢。
避免变量提升陷阱,优先使用 const/let 声明函数表达式
函数声明会被提升(hoisted),而函数表达式不会——这一差异在动态加载场景中尤为关键。
- 如果写
const myUtil = function() { ... };,那么myUtil只有在脚本加载完成、该行代码执行后才存在。这完全符合动态加载的预期行为。 - 切勿在动态
中混用函数声明(例如function myUtil() {}),因为提升机制会导致它在脚本上下文中提前可用,容易引发未定义行为,增加调试难度。 - ES6 的箭头函数也可作为表达式使用,但需注意
this的绑定差异。对于不依赖上下文的工具函数,箭头函数写法更简洁;若涉及this指向,仍应使用普通函数表达式。
