JavaScript,检查嵌套对象属性是不是为空/未定义的优雅方法[重复]
Posted
技术标签:
【中文标题】JavaScript,检查嵌套对象属性是不是为空/未定义的优雅方法[重复]【英文标题】:JavaScript, elegant way to check nested object properties for null/undefined [duplicate]JavaScript,检查嵌套对象属性是否为空/未定义的优雅方法[重复] 【发布时间】:2014-07-11 14:45:41 【问题描述】:我不时遇到的一个“问题”是我有一个对象,例如user =
并在使用该应用程序的过程中填充。假设在某个地方,在 AJAX 调用或我这样做之后:
user.loc =
lat: 50,
long: 9
在另一个地方我想检查user.loc.lat
是否存在。
if (user.loc.lat)
// do something
如果它不存在,这将导致错误。如果user.loc.lat
是undefined
,user.loc
当然也是undefined
。
"Cannot read property 'lat' of null" - Dev Tools error
这意味着我需要像这样检查它:
if (user.loc)
if (user.loc.lat)
// do something
或
if (user.loc && user.loc.lat)
// do something
这不是很漂亮,而且我的对象越大,效果就越差 - 显然(想象一下 10 层嵌套)。
如果user.loc
也是undefined
,if(user.loc.lat)
不只是返回 false
,这让我感到很沮丧。
检查这种情况的理想方法是什么?
【问题讨论】:
试试这个if(user && user.loc && user.loc.lat)
您可以使用typeof检查 null 和 undefined 的值
@AamirAfridi——尽管 OP 是这样写的,但测试应该停止在最后一个对象,而不是属性。例如如果user.loc.lat
存在但具有错误值(例如0
),则测试将返回错误。 :-)
【参考方案1】:
您可以使用惰性and
组合检查:
if(user.loc && user.loc.lat) ...
或者,您使用 CoffeeScript。并且 ES2020 有新的语法( Nullish coalescing Operator )。
user.loc?.lat?. '...'
它将检查loc
属性并防止空对象。
【讨论】:
对不起,你们都回答得很快。您的第一种方法也是我想避免的情况。考虑到我有 5 到 15 层嵌套的巨大对象。 这里没有太多选择。 (1) 手动或使用 CoffeeScript 进行属性检查,(2) try/catch。如果您有一个具有 15 级嵌套的对象,并且它的属性可能在任何级别都不存在,那么我认为您的应用程序有一些次优设计模式。 这是一个例子。我想要一种方法来涵盖这种情况。我显然会避免 15 层嵌套,但如果一个旧的服务器端应用程序就是这样做的,我必须处理它怎么办?这就是为什么我想涵盖那个场景.?
被称为optional chaining operator
。空值合并运算符` (??
) 与 OR 运算符 (||
) 非常不同且更相似。 developer.mozilla.org/en-US/docs/Web/javascript/Reference/….【参考方案2】:
试试这个if(user && user.loc && user.loc.lat) ...
您可以使用typeof检查 null 和 undefined 的值
如果.loc
的值是false
,则可以尝试
if(user && user.loc && typeof(user.loc)!=="undefined")...
如果您有一个巨大的嵌套对象,请查看
Source.
function checkNested(obj /*, level1, level2, ... levelN*/)
var args = Array.prototype.slice.call(arguments),
obj = args.shift();
for (var i = 0; i < args.length; i++)
if (!obj.hasOwnProperty(args[i]))
return false;
obj = obj[args[i]];
return true;
var test = level1:level2:level3:'level3' ;
checkNested(test, 'level1', 'level2', 'level3'); // true
checkNested(test, 'level1', 'level2', 'foo'); // false
更新: 试试lodash.get
【讨论】:
对不起,你们都回答得很快。这也是我想避免的情况。考虑到我有 5 到 15 层嵌套的巨大对象。 我讨厌人们不加评论就拒绝投票。【参考方案3】:你可以使用这样的实用函数:
get = function(obj, key)
return key.split(".").reduce(function(o, x)
return (typeof o == "undefined" || o === null) ? o : o[x];
, obj);
用法:
get(user, 'loc.lat') // 50
get(user, 'loc.foo.bar') // undefined
或者,仅检查属性是否存在,而不获取其值:
has = function(obj, key)
return key.split(".").every(function(x)
if(typeof obj != "object" || obj === null || ! x in obj)
return false;
obj = obj[x];
return true;
);
if(has(user, 'loc.lat')) ...
【讨论】:
爱它!很好的解决方案。 get 方法的问题是它可能从链中的任何地方返回一个属性,它没有专门测试最后一个属性。 @RobG 怎么样?一旦它遇到一个未定义的,它就会一直通过并且结果是未定义的。 我希望 lodash 能和这个函数。_.has
是最接近的,但不检查值。
实际上,从头开始,确实如此!只需使用_.get
***.com/a/24046380/654708【参考方案4】:
好吧,javascript 有 try-catch。根据您实际需要做的事情(即,如果它是 undefined
,您的 else
语句会是什么样子),这可能就是您想要的。
示例:
try
user.loc.lat.doSomething();
catch(error)
//report
【讨论】:
啊当然。也是一个很好的答案,谢谢! 我认为抛出异常而不是 if-else 不是一个好主意,如果您知道 var 可能未设置,我不认为这是一个异常,因此您应该处理它没有尝试捕获。 (当然你可以加入 else 子句)然后。 我喜欢这个解决方案,用于处理有时会因条件句而变得难以阅读的简单内容。 @JonasStensved 指出不使用 try catch 是因为启动异常(我认为,在您编写throw
之前,您不会启动它)但问题可能是块中出现其他问题,您将无法检测到它关于未来。
@pikilon 经验法则:不要使用异常进行流量控制。在您的情况下,某些事情确实出乎意料并且是异常,然后抛出。否则将其作为任何其他代码条件处理。以上是关于JavaScript,检查嵌套对象属性是不是为空/未定义的优雅方法[重复]的主要内容,如果未能解决你的问题,请参考以下文章