使用ExpressJS的EJS模板中检查变量存在的正确方法是什么?

159

在 EJS 的 github 页面上,只有一个简单的示例:

https://github.com/visionmedia/ejs

示例

<% if (user) { %>
    <h2><%= user.name %></h2>
<% } %>

看起来这是在检查名为"user"的变量是否存在,如果存在,则执行一些操作。 显然,对吧?

我的问题是,为什么如果"user"变量不存在,Node会抛出ReferenceError?这使上面的示例无用。有什么适当的方法来检查变量是否存在吗?我需要使用try/catch机制并捕获那个ReferenceError吗?

ReferenceError: user is not defined
    at IncomingMessage.anonymous (eval at <anonymous> (/usr/local/lib/node/.npm/ejs/0.3.1/package/lib/ejs.js:140:12))
    at IncomingMessage.<anonymous> (/usr/local/lib/node/.npm/ejs/0.3.1/package/lib/ejs.js:142:15)
    at Object.render (/usr/local/lib/node/.npm/ejs/0.3.1/package/lib/ejs.js:177:13)
    at ServerResponse.render (/usr/local/lib/node/.npm/express/1.0.7/package/lib/express/view.js:334:22)
    at Object.<anonymous> (/Users/me/Dropbox/Projects/myproject/server.js:188:9)
    at param (/usr/local/lib/node/.npm/connect/0.5.10/package/lib/connect/middleware/router.js:146:21)
    at pass (/usr/local/lib/node/.npm/connect/0.5.10/package/lib/connect/middleware/router.js:162:10)
    at /usr/local/lib/node/.npm/connect/0.5.10/package/lib/connect/middleware/router.js:152:27
    at Object.restrict (/Users/me/Dropbox/Projects/myproject/server.js:94:5)
    at param (/usr/local/lib/node/.npm/connect/0.5.10/package/lib/connect/middleware/router.js:146:21)
我知道可以通过在服务器代码中添加一个"用户"本地变量来消除这个错误,但这里的重点是我想使用您每天使用的if/else空值检查类型模式在运行时检查这些变量的存在。对于不存在的变量的异常对我来说似乎很荒谬。
20个回答

198

您可以像处理js中的任何内容一样进行操作,typeof foo == 'undefined',或者由于"locals"是包含这些对象的对象名称,因此您可以执行if (locals.foo)。这只是原始js :p


4
我开始怀疑手头的问题可能更大了。这也会抛出一个“Reference Error(引用错误)”:<% alert('test'); %>。 - Aashay Desai
2
@Aashay alert 是浏览器的 window 对象的一部分,不可在 node.js 中使用。替代方案是 console.log,但我不确定它是否在 ejs 模板中可用,除非您通过 locals 传递它。 - Zikes
2
@Zikes 在这种情况下,我特别寻找EJS,因此它在浏览器页面上。但是,就像TJ所说,typeof foo == 'undefined'可以工作。我学到了如果foo已经被定义但为空或null,我也可以添加一个简单的!!foo。 - Aashay Desai
24
有没有这个的速记?为什么EJS不直接支持if (foo)的情况? - mattdlockyer
10
如果(locals.user){ } FTW. 意思是,如果locals对象中存在user属性,则执行花括号内的代码。"FTW"可能表示"For The Win",表示肯定的情感或赞美。 - s2t2
显示剩余4条评论

49

尝试使用locals在变量前面增加前缀。

例如:if(locals.user){}


33
<% if (locals.user) { %>

 // Your logic goes here 

<% } %>

15

您可以创建一个视图辅助函数,检查“obj === void 0”,这是针对express.js的:

res.locals.get = function() {
    var args = Array.prototype.slice.call(arguments, 0);
    var path = args[0].split('.');
    var root = this;
    for (var i = 0; i < path.length; i++) {
        if(root[path[i]] === void 0) {
            return args[1]?args[1]:null;
        } else {
            root = root[path[i]];
        }
    };
    return root;
}

然后在视图中像这样使用它:

<%- get('deep.nested.non.existent.value') %>  //returns: null
<%- get('deep.nested.non.existent.value', "default value") %> //returns: default value

3
不确定为什么这被踩了,我认为它相当优雅。 - joseym
<%=<%- 有什么区别? - NobleUplift
2
根据文档中的说明,在“标签”下:<%=会首先对HTML进行转义,而<%-则输出未经转义的值。因此,当使用<%-时,<b>将变成粗体标记,但是当使用<%=时,它只是文本"<b>"。@NobleUplift - Matheus Avellar
谢谢!我甚至不知道<%-是一个有效的标签。 - NobleUplift
1
我知道这是一个很久以前的帖子,但我该如何实现它?我尝试了自己,但找不到如何正确地将其转换为助手程序。谢谢。 - Jonathan Lafleur

12

要检查用户是否已定义,您需要执行以下操作:

<% if (this.user) { %>
   here, user is defined
<% } %>

4
在最新的EJS库(1.0.0)中,这种方法不起作用。尽管它是有效的JavaScript代码,但EJS无法按预期工作。 - Axoren
6
对我来说不起作用。即使我已经定义了 foo,else 语句仍然会被评估。使用 EJS 2.3.4 进行测试。编辑:使用 locals 替代 this 可行。 - X_Trust

9

我在使用node.js、mongoose/express/ejs时遇到了同样的问题,当使用mongoose的populate()方法建立两个集合之间的关系时,发现admins.user_id存在但与不存在的users._id相关联。
所以,无法找到原因:

if ( typeof users.user_id.name == 'undefined' ) ...

出现错误信息"Cannot read property 'name' of null",后来我发现需要像这样进行检查:

if ( typeof users.user_id == 'undefined' ) ...

我需要检查'name'的"容器",这样它就可以工作了!
之后,这个也能够正常工作:

if ( !users.user_id ) ...  

希望这能帮到你。

无论如何,我无法相信 EJS 官方文档这么少...自从 2010 年以来,他们就没有更新过文档!!! - aesede

4
这可能对某些人有所帮助。
<p><%= locals?.message %></p>

或者
<p><%= locals.message || '' %></p>

3

我来到这个页面寻找答案,但是我想出了一种更短的内联语法:

 <h2><%= user.name ? property.escrow.emailAddress : '' %></h2>

3
如果对象'user'没有'name'属性,使用这个可能会很危险,因为ejs渲染将无法正常进行。 - Marko Rochevski

2

在您的 if 语句中,您需要使用 typeof

<% if (typeof user == 'object' && user) { %>

<% } %>

2

更新 2022

使用 locals 对象

如果变量存在,则会打印该变量

<%= locals?.yourvariable %>

你也可以这样做

如果变量存在,这将运行一个条件

<% if(locals.yourvariable) { %>
<% } %>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接