
本文讲解如何在模板字符串生成的 html 中正确调用外部定义的 javascript 函数(如 `page()`),避免因作用域或执行时机问题导致的 `referenceerror: page is not defined` 错误。核心在于确保函数全局可访问、作用域正确,且不依赖未初始化环境。
在使用模板字符串动态插入 HTML 并绑定内联事件(如 onclick="page('xxx')")时,JavaScript 会将该字符串解析为 DOM 后,在点击时刻尝试从全局作用域查找 page 函数。若 page 未声明为全局函数(例如被包裹在模块、IIFE 或其他作用域中),或其定义语句位于 render() 调用之后(JS 执行顺序问题),就会触发 Uncaught ReferenceError: page is not defined。
✅ 正确做法是:确保 page() 是可被全局访问的命名函数,且定义早于任何 HTML 插入操作。
以下是一个完整、可运行的示例:
点击下方卡片测试
? 关键注意事项:
- 作用域陷阱:不要将 page 定义在 render 内部、模块顶层(ESM 默认无全局污染)、或 IIFE 中——除非你显式挂载到 window.page = ...;
- 执行时机:内联 onclick 是字符串求值,仅支持全局函数调用,不支持箭头函数、局部变量或未提升的函数表达式;
- 安全性提醒:内联事件 + 字符串拼接存在 XSS 风险(尤其当 numberFolder 来自用户输入)。生产环境推荐使用事件委托 + addEventListener:
// 更安全的替代方案(推荐)
function renderSafe(img, name, price, folderNum) {
const a = document.createElement('a');
a.className = 'ProductCard';
a.href = '#';
a.innerHTML = `
@@##@@
${name}
¥${price}
立即学习“Java免费学习笔记(深入)”;
`;
a.dataset.folder = folderNum; // 使用 data 属性传递参数
a.addEventListener('click', (e) => {
e.preventDefault();
page(a.dataset.folder); // 安全、可控、无 XSS 风险
});
document.querySelector('#main').appendChild(a);
}? 总结:字符串中的 onclick 不是“无法执行函数”,而是要求函数必须在全局作用域中可用。优先采用 addEventListener 方案,兼顾可维护性、安全性和调试友好性。









