检查 JavaScript 中是不是存在深度嵌套对象属性的最简单方法是啥? [复制]
Posted
技术标签:
【中文标题】检查 JavaScript 中是不是存在深度嵌套对象属性的最简单方法是啥? [复制]【英文标题】:What's the simplest approach to check existence of deeply-nested object property in JavaScript? [duplicate]检查 JavaScript 中是否存在深度嵌套对象属性的最简单方法是什么? [复制] 【发布时间】:2011-10-19 03:02:22 【问题描述】:我必须检查深度嵌套的对象属性,例如 YAHOO.Foo.Bar.xyz。
我目前使用的代码是
if (YAHOO && YAHOO.Foo && YAHOO.Foo.Bar && YAHOO.Foo.Bar.xyz)
// operate on YAHOO.Foo.Bar.xyz
这可行,但看起来很笨拙。
有没有更好的方法来检查这种深度嵌套的属性?
【问题讨论】:
你不能只做if (YAHOO.Foo.Bar.xyz)
吗?
enterprise-js.com/34
@Michael,你不能只做if (YAHOO.Foo.Bar.xyz)
,因为如果 Foo 或 Bar 不存在,那么 if (YAHOO.Foo.Bar.xyz)
会因为取消引用未定义的中间值而引发异常。
这可能是最好的检查方法;使用try...catch
会影响性能——当抛出异常时,代码会变慢。 jsPerf test.
@Digital Plane - 但是,如果正常情况是它存在,那么 try/catch 比多重 if 测试(在 Chrome 中)快 19 倍。
【参考方案1】:
如果您希望YAHOO.Foo.Bar
是一个有效的对象,但又想让您的代码防弹以防万一它不是,那么在它周围放置一个 try catch 并让一个错误处理程序捕获任何可能是最干净的缺失的部分。然后,您可以只使用一个 if
条件而不是四个来检测终端属性是否存在,如果中间对象不存在,则使用一个 catch 处理程序来捕获事物:
try
if (YAHOO.Foo.Bar.xyz)
// operate on YAHOO.Foo.Bar.xyz
catch(e)
// handle error here
或者,根据您的代码的工作方式,它甚至可能只是这样:
try
// operate on YAHOO.Foo.Bar.xyz
catch(e)
// do whatever you want to do when YAHOO.Foo.Bar.xyz doesn't exist
在处理应该是特定格式的外部输入时,我特别使用这些,但无效输入是我想要捕获和处理自己的可能性,而不是仅仅让异常向上传播。
一般来说,一些 javascript 开发人员未充分使用 try/catch。我发现有时我可以用围绕较大功能块的单个 try/catch 替换 5-10 if 语句检查输入,同时使代码更简单且更具可读性。显然,何时合适取决于特定的代码,但绝对值得考虑。
仅供参考,如果通常的操作是不使用 try/catch 抛出异常,它也可以比一堆 if 语句快得多。
如果您不想使用异常处理程序,您可以创建一个函数来为您测试任意路径:
function checkPath(base, path)
var current = base;
var components = path.split(".");
for (var i = 0; i < components.length; i++)
if ((typeof current !== "object") || (!current.hasOwnProperty(components[i])))
return false;
current = current[components[i]];
return true;
示例用法:
var a = b: c: d: 5;
if (checkPath(a, "b.c.d"))
// a.b.c.d exists and can be safely accessed
【讨论】:
不要这样滥用try catch。亲爱的上帝,我的眼睛。甚至是一个空的 catch 块。如果我见过的话,这是一种代码味道。 @Raynos - 为什么这会滥用 try/catch?对我来说,检查所有中间级别比使用多个嵌套 if 语句更有意义。一个空的捕获只是意味着如果中间级别不存在,你故意不做任何事情(一个合理的设计选择)。这是非常好的代码。您是否真的因为喜欢不同的方法而投反对票?像这样使用 try/catch 绝对没有错。 “异常的发生,改变程序正常执行流程的特殊情况。”我发现声称不存在的属性是“改变程序执行正常流程的特殊条件”是一个巨大的延伸。我认为您使用了错误的工具来完成这项工作。 当您通常期望它存在时不存在的中间属性很可能是“改变程序正常执行流程的特殊条件”,并且似乎是异常的完美用途。您似乎认为异常应该只用于特殊的事情,但它们只是另一种错误返回/传播机制,在许多情况下可以比多个if
语句更有效地使用,特别是当您处理外国您不一定要控制的输入,并且测试每个操作可能会非常昂贵。
在处理应该遵守特定格式但可能有错误的外来 html(不受我控制的 HTML)时,我一直使用异常。当一开始有一堆家务(解析结构,获取数据等),然后在最后应用最终结果时,它特别有用。我用 try/catch 包围整个块,如果任何结构不符合预期,它会引发错误,并且我非常有效地在一个地方捕获所有错误,而不是使用数十个 if
语句。也使代码更具可读性。【参考方案2】:
coffeescript(编译成javascript)很好地解决了这个问题:
if YAHOO.Foo?.Bar?.xyz
// operate on YAHOO.Foo.Bar.xyz
【讨论】:
【参考方案3】:考虑这个效用函数:
function defined(ref, strNames)
var name;
var arrNames = strNames.split('.');
while (name = arrNames.shift())
if (!ref.hasOwnProperty(name)) return false;
ref = ref[name];
return true;
用法:
if (defined(YAHOO, 'Foo.Bar.xyz'))
// operate on YAHOO.Foo.Bar.xyz
现场演示: http://jsfiddle.net/DWefK/5/
【讨论】:
我认为您需要在 while 循环测试中明确检查 undefined,而不仅仅是真实性测试。此刻定义(a:'','a.b')=== true。不错的方法,我喜欢它! @codebox 我对我的代码不满意,所以我重写了。你怎么看? 我希望在下划线或 lodash 中有这样的内容 哦 lodash 确实有。 _.get(),太棒了!甚至还有一个默认参数。 这是一个非常好的解决方案。但是如果引用对象未定义,代码就会中断。我认为检查是否定义了引用对象将解决问题。 Your solution, Updated one【参考方案4】:var _ = ;
var x = ((YAHOO.Foo || _).Bar || _).xyz;
【讨论】:
为本周最不清楚的一行点赞。【参考方案5】:我实际上投票结束了作为javascript convert dotnotation string into objects重复的问题。
但是,我想这是一个不同的主题,但如果您不想一直try-catch
,那么那里的答案可能仍然有用。
【讨论】:
【参考方案6】:如果您需要检查路径的正确性,而不是“YAHOO.Foo.Bar”对象上是否存在“xyz”成员,将调用包装在 try catch 中可能是最简单的:
var xyz;
try
xyz = YAHOO.Foo.Bar.xyz;
catch (e)
// fail;
;
或者,你可以做一些 string-kong-fu-magicTM:
function checkExists (key, obj)
obj = obj || window;
key = key.split(".");
if (typeof obj !== "object")
return false;
while (key.length && (obj = obj[key.shift()]) && typeof obj == "object" && obj !== null) ;
return (!key.length && typeof obj !== "undefined");
用法如下:
if (checkExists("YAHOO.Foo.Bar.xyz"))
// Woo!
;
【讨论】:
你什么时候会使用 checkExists 函数中涉及的所有东西而不是 try/catch 方法? 我只是不明白typeof obj !== "object"
测试的意义。为什么要限制?
@jfriend00:字符串方法可以让您找到事情发生故障的点(如果您也想这样做的话)。在某些情况下,通过字符串传递对象描述也是有意义的,例如自定义模块系统。
@missingno:它检查用户提供的“obj”(这是可选的;如果没有提供,它默认为window
),实际上是一个对象(它阻止函数中断如果用户传递了错误的参数,基本上!)
@jfriend00:try/catch
如果您有很多地方要检查对象路径是否存在,则有点需要输入。【参考方案7】:
使用try catch
。
a=
b:
;
//a.b.c.d?true:false; Errors and stops the program.
try
a.b.c.d;
catch(e)
console.log(e);//Log the error
console.log(a.b);//This will run
【讨论】:
以上是关于检查 JavaScript 中是不是存在深度嵌套对象属性的最简单方法是啥? [复制]的主要内容,如果未能解决你的问题,请参考以下文章