这些跨浏览器Javascript函数中哪一个表现更好?

3
作为一个经验法则,哪种编写跨浏览器Javascript函数的方法会更高效? 方法1
function MyFunction() 
{
    if (document.browserSpecificProperty)
       doSomethingWith(document.browserSpecificProperty);
    else
       doSomethingWith(document.someOtherProperty);
}

方法2

var MyFunction;
if(document.browserSpecificProperty) {
    MyFunction = function() {
       doSomethingWith(document.browserSpecificProperty);
    };
} else {
    MyFunction = function() {
       doSomethingWith(document.someOtherProperty);
    };
}

编辑:感谢所有优秀答案的点赞。我已将函数修正为更正确的语法。

以下是关于迄今为止所提供答案的几点说明——虽然在大多数情况下,这是一个没有意义的性能增强,但仍有一些原因需要花费一些时间分析代码:

  • 必须在慢速计算机、移动设备、旧浏览器等上运行。
  • 好奇心。
  • 使用相同的一般原则来增强其他场景的性能,其中 IF 语句的评估确实需要一些时间。

唉,这并不是真正的跨浏览器代码,因为它依赖于仅在 Mozilla 中出现的行为。 - olliej
7个回答

16

除非您要执行此操作一万亿次,否则并不重要。选择更易读和可维护的选项适合您和/或您的组织。编写干净、简单代码所获得的生产力增益比缩短JS执行时间1/10微秒要重要得多。

只有在编写的代码速度不可接受时,您才应开始考虑性能问题。然后您应该开始查找瓶颈,而这将永远不会是像这样的问题。从其中一个切换到另一个,您永远不会获得可衡量的性能提升。


7
很遗憾,上面的代码实际上并不支持跨浏览器,因为它依赖于mozilla中存在的一个怪癖,而其他浏览器没有这个问题 -- 也就是说,在分支内部将function 声明视为function 表达式。在非基于mozilla构建的其他浏览器中,上述代码始终会使用第二个函数定义。我制作了一个简单的测试用例来证明这一点,链接在这里
基本上,ECMAScript规范表示,函数语句与变量声明类似处理,例如,它们都提升到当前执行范围的顶部(例如,

3
为了澄清olliej的回答,你的第二种方法在技术上是一个语法错误。你可以这样重写它:
var MyFunction;
if(document.browserSpecificProperty) {
    MyFunction = function() {
       doSomethingWith(document.browserSpecificProperty);
    };
} else {
    MyFunction = function() {
       doSomethingWith(document.someOtherProperty);
    };
}

这至少是正确的语法,但请注意MyFunction只能在该范围内使用。 (省略var MyFunction;,最好使用window.MyFunction = function() ...来进行全局调用。)


实际上这不是语法错误,而且是完全有效的JS代码,只是它可能不会做你想要的事情。这很像var的行为,因为人们期望JS对vars使用语法作用域,但实际上它只对函数进行作用域限制。 - olliej
据我理解,这实际上是一个语法错误。也许我的理解是错误的。我需要重新阅读规范的相关部分,但不幸的是我现在无法做到。我将删除我回答中的那部分内容。 - eyelidlessness
我将重新检查规范--我知道所有的JS引擎都会解析它,所以它可能已经成为事实上的语法,即使它不能做想要的事情。 - olliej
啊哈,你说得对,按照规范来说,它应该是一个解析错误,因为FunctionDeclaration生产仅出现在SourceElement生产内而非语句。所以我道歉,你是对的--从技术上讲确实是语法错误。 - olliej
回滚了。我记得曾经读到一篇对Prototype的批评,称其为语法错误,所以我查阅了规范并得出他们是正确的结论(在这一点上)。但是我的实际规范记忆已经模糊了。感谢在我回去之前检查它。 :) - eyelidlessness
那个给这个回答点踩的人想解释一下为什么吗? - eyelidlessness

2
从技术上讲,我认为第二个函数的性能更好,因为if语句只执行一次,而不是每次运行函数都要执行一次。
然而,差别微乎其微,几乎没有任何意义。单个if语句的性能惩罚甚至与调用函数的性能惩罚相比也微不足道。即使if被调用了一百万次,它的影响也很小。
第一个函数更容易理解,因为它没有根据条件定义相同的函数两次,并且两个版本的行为不同,这似乎会导致以后的混淆。
我不是第一个说除非你真的疯狂于这种优化,否则你将从代码可读性中获得更多收益的人。

不确定为什么这篇文章会收到这么多的负评 - 如果您认为我错了,能否请您解释一下原因。 - thomasrutter

0
通常我更喜欢第二个版本,因为条件只需要在第一次评估时进行一次而不是每次调用都要进行,但有时候这并不可行,因为它会影响可读性。
顺便说一下,这是一个你可能想使用 ?: 运算符的情况,例如(摘自生产代码):
var addEvent =
    document.addEventListener ? function(type, listener) {
        document.addEventListener(type, listener, false);
    } :
    document.attachEvent ? function(type, listener) {
        document.attachEvent('on' + type, listener);
    } :
    throwError;

0

针对您的简化示例,假设您的浏览器属性检查只需要执行一次,我会执行以下操作:

var MyFunction = (function() {

      var rightProperty = document.browserSpecificProperty || document.someOtherProperty;

      return function doSomethingWith() {
            // use the rightProperty variable in your function
      }
})();

0

性能应该几乎相等!

考虑使用像JQuery这样的框架来摆脱浏览器兼容性问题!

如果性能是您的主要目标,请查看SlickSpeed! 这是一个对比不同JavaScript框架的页面!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接