我来自编译语言背景(C / C ++ / Objective-C),目前正在用JavaScript编写一个成熟的应用程序。 (实际上是TypeScript,但我的问题对于两者都是一样的。)
我遇到的问题是,如果发生单个错误,整个执行流程将停止。例如,如果我有:
myFunction()
{
doSomethingA();
doSomethingB();
doSomethingC();
}
然后如果doSomethingA()有这样的东西:
var myValue = window.myData.myValue;
但当时“myData”在“窗口”上不存在,则所有代码STOPS EXECUTING ... doSomethingB()和doSomethingC()都不会执行,并且会记录控制台错误。对于简单的网页来说这可能没问题,但我正在创建一个应用程序,它不需要莫名其妙地“停止工作”。
当然,我可以使用try / catch来“了解”这个错误,但是STILL并没有解决我的问题:我想以doSomethingB()和doSomethingC()继续的方式编写代码即使出现问题也要执行。 但是,这对我的代码来说是一个巨大的过度简化。想象一下,这些功能有很多。用每个独立的try / catch块包围它们是不切实际的。即使我这样做,我也需要给定函数的其余继续执行,即使第一部分中的某些内容失败。
当然,我可以通过使用以下方式“保护”我的变量:
if ( typeof window.myData != "undefined")
或
if (window.myData.hasOwnProperty("myValue")
但是如果您要检查多个级别(例如访问时),则会变得非常混乱:
var myValue = window.myData.something.anotherLevel.somethingElse.value;
现在我必须检查myData,something,anotherLevel和somethingElse是否全部有效,然后才能“安全”地访问此值。这导致代码非常难看。
有没有更好的方法让我的代码更“防弹”?如果属性意外丢失,我需要在问题陈述后继续执行代码。如果没有“保护”每一个访问数据甚至很少被定义的数据的语句,这是否可能?
答案 0 :(得分:5)
这就是JavaScript的方式。它不是强类型语言。您有正确的方法检查falsy / undefined。您可以查看一个实用程序库,例如Lodash的isUndefined()
方法,以帮助缓解疼痛。它们有很多辅助方法,比如检查对象类型,数组,对象文字等等。
答案 1 :(得分:3)
通常你必须有一些“嵌套如果地狱”,如:
dplyr
为了减轻开发人员的痛苦,有一些实用工具,例如lodash
它非常有用并且缩短了您的代码。
它有_.get(object, path)函数,它按路径获取元素,如果没有找到它只返回undefined。
if(typeof window.myData !== 'undefined' && typeof window.myData.something !== 'undefined' && typeof window.myData.something.anotherlevel !== 'undefined' ...) {
}
答案 2 :(得分:1)
您最好的选择是检查您使用的变量是否未定义
typeof window.yourVariable === "undefined"
然而,依赖窗口对象中的变量,使用范围和闭包不是很安全。
答案 3 :(得分:0)
我接受了前缀的答案,因为我不喜欢接受我自己的答案。而且,听听Lodash帮手是有用的,并且知道如果地狱"嵌套了#34;我是JavaScript的一个正常(伤心地听到它!)的一部分。
然而,&#39>解决方案'我已经离开了,最终让我感到非常高兴,实际上是在我原来的问题中拒绝一个前提:try / catch不是一个好的解决方案。
结果是try / catch,结合尝试确保变量未定义,是抓住我错过的那些案例的好方法。
我实际上最终设计如下。让我们说我有很多函数我希望由于doStuff()而发生,并且我已将它们放入window.callbacks中。然后我可以做(未经测试的伪代码,但它给你的要点):
doStuff() {
for (var myFunc in window.callbacks) {
if (window.callbacks.hasOwnProperty(myFunc) ) {
try {
window.callbacks[myFunc].call();
}
catch(err) {
console.log("%cCaught error in " + myFunc + ": " + (err.stack || err), 'background: #222; color: #bada55');
}
}
}
}
这会记录一个唯一的控制台日志消息,其中包含堆栈跟踪,显示触发错误的内容,但代码执行仍然存在。仍将调用后续回调。唯一没有执行的代码是导致错误的回调的剩余部分。
鉴于我的编译语言背景,这给了我温暖的模糊感觉......这意味着在最坏的情况下,一个小函数将无法执行,而不是错误后的整个代码路径。