Javascript Try-Catch Performance Vs. 检查代码时出错

Abe*_*Abe 31 javascript try-catch

将代码放入try-catch块而不是执行各种错误检查会更快吗?

例如..

function getProjectTask(projectTaskId) {
    if (YAHOO.lang.isUndefined(projectTaskId) || YAHOO.lang.isNull(projectTaskId) && !YAHOO.lang.isNumber(projectTaskId)) {
        return null;
    }

    var projectPhaseId, projectPhaseIndex, projectTaskIndex, projectPhases, projectPhase, projectTask;

    if (!YAHOO.lang.hasOwnProperty(projectTaskPhaseMap, projectTaskId)) {
        return null;
    }

    projectPhaseId = projectTaskPhaseMap[projectTaskId];

    if (YAHOO.lang.isUndefined(projectPhaseId) || YAHOO.lang.isNull(projectPhaseId) || !YAHOO.lang.hasOwnProperty(scheduleData.ProjectPhasesMap, projectPhaseId)) {
        return null;
    }

    projectPhaseIndex = scheduleData.ProjectPhasesMap[projectPhaseId];
    if (YAHOO.lang.isUndefined(projectPhaseIndex) || YAHOO.lang.isNull(projectPhaseIndex) || !YAHOO.lang.hasOwnProperty(scheduleData.ProjectPhases[projectPhaseIndex])) {
        return null;
    }
    projectPhase = scheduleData.ProjectPhases[projectPhaseIndex];

    if (!YAHOO.lang.hasOwnProperty(projectPhase.ProjectTasksMap, projectTaskId)) {
        return null;
    }

    projectTaskIndex = projectPhase.ProjectTasksMap[projectTaskId];

    if (YAHOO.lang.isUndefined(projectTaskIndex) || YAHOO.lang.isNull(projectTaskIndex)) {
        return null;
    }

    projectTask = scheduleData.ProjectTasks[projectTaskIndex];
}
Run Code Online (Sandbox Code Playgroud)

VS

function getProjectTask(projectTaskId) {
    try {
        projectPhaseId = projectTaskPhaseMap[projectTaskId];
        projectPhaseIndex = scheduleData.ProjectPhasesMap[projectPhaseId];
        projectPhase = scheduleData.ProjectPhases[projectPhaseIndex];
        projectTaskIndex = projectPhase.ProjectTasksMap[projectTaskId];
        projectTask = scheduleData.ProjectTasks[projectTaskIndex];

    }
    catch (e) {
        return null;
    }
}
Run Code Online (Sandbox Code Playgroud)

我希望我的问题有道理.我很乐意澄清.谢谢!

gbl*_*zex 47

"必须编写程序供人们阅读,并且只有偶然的机器才能执行."

Abiz&Sussman,SICP,第一版序言

始终以可读代码为目标.要记住的关键是:

避免在性能关键函数和循环中使用try-catch

在其他任何地方他们都不会造成太大伤害 明智地使用它们,谨慎使用它们.作为旁注,如果你想支持旧浏览器,他们可能没有try-catch.

但正如我看到你明显滥用一些函数进行错误检查.您可以在使用对象之前测试所需的对象和属性,而不是复杂的检查.和:

if (YAHOO.lang.isUndefined(projectPhaseId) || YAHOO.lang.isNull(projectPhaseId))
Run Code Online (Sandbox Code Playgroud)

可写成

if (projectPhaseId != null)
Run Code Online (Sandbox Code Playgroud)

例如......所以上面的例子即使没有尝试捕获也可以相当可读.你似乎有点误用了 YUI.

我敢打赌这可以按预期工作:

function getProjectTask(projectTaskId) {

   var projectPhaseId    = projectTaskPhaseMap[projectTaskId],
       projectPhaseIndex = scheduleData.ProjectPhasesMap[projectPhaseId],
       projectPhase      = scheduleData.ProjectPhases[projectPhaseIndex];

  if (projectPhase == null) return null; // projectPhase would break the chain

  var projectTaskIndex  = projectPhase.ProjectTasksMap[projectTaskId],
      projectTask       = scheduleData.ProjectTasks[projectTaskIndex];

   return projectTask || null; // end of the dependency chain

}
Run Code Online (Sandbox Code Playgroud)

这有多?:)

  • 说得好.我想补充说,除非你确实遇到性能问题,否则最好让你的代码可读.当您确实遇到性能问题时,首先测量问题所在,然后再进行优化.否则你可能会花很多时间来优化错误的东西. (10认同)

小智 28

为什么没有这个论点的事实依据?以下代码演示了性能影响:

var Speedy = function() {
    this.init();
};
Speedy.prototype = {
    init: function() {
        var i, t1;
        this.sumWith = 0;
        this.sumWithout = 0;
        this.countWith = 0;
        this.countWithout = 0;
        for (i = 0; i < 5; i++) {
            t1 = this.getTime();
            console.log("Using Try/Catch, Trial #" + (i + 1) );
                        console.log("started " + t1 );
            this.goTry(t1);
            this.countWith++;
        }
        for (i = 0; i < 5; i++) {
            t1 = this.getTime();
            console.log("W/out Try/Catch, Trial #" + (i + 1) );
            console.log("started  :" + t1 );
            this.goAlone(t1);
            this.countWithout++;
        }
        for (i = 5; i < 10; i++) {
            t1 = this.getTime();
            console.log("Using Try/Catch, Trial #" + (i + 1) );
            console.log("started  :" + t1);
            this.goTry(t1);
            this.countWith++;
        }
        for (i = 5; i < 10; i++) {
            t1 = this.getTime();
            console.log("W/out Try/Catch, Trial #" + (i + 1) );
            console.log("started  :" + t1);
            this.goAlone(t1);
            this.countWithout++;
        }
        console.log("---------------------------------------");
        console.log("Average time (ms) USING Try/Catch: " + this.sumWith / this.countWith + " ms");
        console.log("Average time (ms) W/OUT Try/Catch: " + this.sumWithout / this.countWithout + " ms");
        console.log("---------------------------------------");
    },

    getTime: function() {
        return new Date();
    },

    done: function(t1, wasTry) {
        var t2 = this.getTime();
        var td = t2 - t1;
        console.log("ended.....: " + t2);
        console.log("diff......: " + td);
        if (wasTry) {
            this.sumWith += td;
        }
        else {
            this.sumWithout += td;
        }
    },

    goTry: function(t1) {
        try {
            var counter = 0;
            for (var i = 0; i < 999999; i++) {
                counter++;
            }
            this.done(t1, true);
        }
        catch (err) {
            console.error(err);
        }
    },

    goAlone: function(t1) {
        var counter = 0;
        for (var i = 0; i < 999999; i++) {
            counter++;
        }
        this.done(t1, false);
    }
};

var s = new Speedy();
Run Code Online (Sandbox Code Playgroud)

这个JSFiddle将在firebug lite的控制台中显示输出:http://jsfiddle.net/Mct5N/

  • 上面的实现不再有效(jsFiddle不喜欢`document.writeln`).这是一个更新版本:http://jsfiddle.net/Mct5N/ (6认同)
  • 嘿哇,你真的回答了这个问题!:) (2认同)