如何使JavaScript代码更具防弹性?

时间:2016-06-21 21:37:30

标签: javascript web typescript

我来自编译语言背景(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是否全部有效,然后才能“安全”地访问此值。这导致代码非常难看。

有没有更好的方法让我的代码更“防弹”?如果属性意外丢失,我需要在问题陈述后继续执行代码。如果没有“保护”每一个访问数据甚至很少被定义的数据的语句,这是否可能?

4 个答案:

答案 0 :(得分:5)

这就是JavaScript的方式。它不是强类型语言。您有正确的方法检查falsy / undefined。您可以查看一个实用程序库,例如Lodash的isUndefined()方法,以帮助缓解疼痛。它们有很多辅助方法,比如检查对象类型,数组,对象文字等等。

https://lodash.com/docs#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');
            }
       }
   }
}

这会记录一个唯一的控制台日志消息,其中包含堆栈跟踪,显示触发错误的内容,但代码执行仍然存在。仍将调用后续回调。唯一没有执行的代码是导致错误的回调的剩余部分。

鉴于我的编译语言背景,这给了我温暖的模糊感觉......这意味着在最坏的情况下,一个小函数将无法执行,而不是错误后的整个代码路径。