
本文详解 Node.js + Express 应用中因模板数据传递与变量名不匹配导致的 ReferenceError: xxx is not defined 错误,重点说明 res.render() 传入对象键名与 EJS 中实际引用变量名必须严格一致的核心原则,并提供可立即验证的修复方案。
本文详解 node.js + express 应用中因模板数据传递与变量名不匹配导致的 `referenceerror: xxx is not defined` 错误,重点说明 `res.render()` 传入对象键名与 ejs 中实际引用变量名必须严格一致的核心原则,并提供可立即验证的修复方案。
在 Express 应用中使用 EJS 渲染模板时,一个高频且易被忽略的错误是:模板中引用的变量名与 res.render() 传递的数据对象中的键名不一致。这将直接触发 ReferenceError —— 例如你遇到的 articles is not defined,其根本原因并非变量未声明,而是服务端根本没有向模板暴露名为 articles 的变量。
回顾你的代码逻辑:
-
在路由文件中,你调用了:
res.render('author', { author: articles })这表示:将 articles 数组作为值,以 author 为键名注入到 EJS 模板的作用域中。
-
但在 author.ejs 模板中,你却写了:
<% articles.forEach(article => { %>此时 EJS 引擎会在当前作用域查找名为 articles 的变量,但实际只存在 author —— 因此抛出 ReferenceError。
✅ 正确做法有两种(任选其一,保持语义清晰更推荐方案一):
✅ 方案一:修改模板,匹配传入的键名(推荐)
<!-- author.ejs -->
<% author.forEach(article => { %>
<div class="card mt-4">
<div class="card-body">
<h4 class="card-title"><%= article.title %></h4>
<div class="card-subtitle text-muted mb-2">
<%= article.createdAt.toLocaleDateString() %>
</div>
<!-- 注意:原模板中使用了 article.description,但示例数据中无该字段 -->
<!-- 建议改为 article.subtitle 或补充数据 -->
<div class="card-text mb-2"><%= article.subtitle || 'No subtitle' %></div>
</div>
</div>
<% }) %>✅ 方案二:修改渲染逻辑,统一使用 articles 键名
// 路由文件中(如 author.js 或对应 router 文件)
router.get('/home', (req, res) => {
const articles = [{
title: 'test article',
subtitle: 'test subtitle',
createdAt: new Date(),
lastModified: new Date()
}];
// 关键修改:将键名设为 'articles'
res.render('author', { articles }); // 等价于 { articles: articles }
});随后模板中即可安全使用:
<% articles.forEach(article => { %>
<!-- ... -->
<% }) %>⚠️ 重要注意事项:
- EJS 模板中的变量完全依赖 res.render() 第二个参数(即数据对象)的键名,不存在自动“解构”或“全局提升”;
- 变量名区分大小写,Articles ≠ articles;
- 若模板中访问了数据中不存在的属性(如 article.description),虽不报 ReferenceError,但会渲染 undefined,建议使用 || 提供默认值或使用 <% if (article.subtitle) { %> 做存在性判断;
- 确保 .ejs 文件路径正确(如 views/author.ejs),且 app.set('views', path.join(__dirname, 'views')) 已正确定义。
? 快速验证步骤:
- 检查路由中 res.render('xxx', { key: value }) 的 key;
- 打开对应 xxx.ejs,确认所有 <%= 和 <% 中引用的变量名与 key 完全一致;
- 重启服务,刷新页面。
遵循“传什么名,就用什么名”的原则,即可彻底规避此类 ReferenceError。这是 Express + EJS 开发中最基础也最关键的约定之一。










