【问题标题】:Performance of OOJS over functional JavaScript programmingOOJS 相对于函数式 JavaScript 编程的性能
【发布时间】:2011-06-06 13:57:12
【问题描述】:

这个问题与之前的问题有关:

Reducing number of calls to the methods of a JavaScript object

使用 Firebug 分析这两个代码 sn-ps 时:

function ie6PNGFixLoader(scriptURL) {
    if(arguments.length > 0) {
        for (var i = 0; i < arguments.length; i++) {
            $.ajax({// load PNG fix scripts
                url: arguments[i],
                cache: true,
                dataType: 'script'
            });
        }
    } else {
        return false;
    }               
}

var pngFix = "/Global/ICIS/Scripts/DD_belatedPNG_0.0.8a-min.js";    
var pngList = "/Global/ICIS/Scripts/DD_PNG_listing.js"; 
ie6PNGFixLoader(pngFix, pngList);

function InjectScriptsAndExecute(url) {
    this.url = url;
}

InjectScriptsAndExecute.prototype.InjectMethod = function() {
    var inject = $.ajax({
                        url: this.url,
                        cache: true,
                        dataType: 'script',
                        async: false, // Otherwise you cannot depend on the parse order
                        }); 
    return inject;  
}
var pngFix = new InjectScriptsAndExecute("/Global/ICIS/Scripts/DD_belatedPNG_0.0.8a-min.js");
var pngList = new InjectScriptsAndExecute("/Global/ICIS/Scripts/DD_PNG_listing.js");
pngFix.InjectMethod();
pngList.InjectMethod();

显然后者对 InjectScriptsAndExecute 方法的调用比前者对其函数的调用要快得多。一位同事问我为什么当我提到性能改进但我自己无法解释时。

我们将非常欢迎任何有助于更好理解的建议。

【问题讨论】:

  • 你将不得不发布更多关于你的性能测量的信息。它们之间的主要区别不是编码风格(这几乎不会产生可测量的差异),而是 ajax 操作的不同设置(异步与同步)。

标签: javascript performance oop object functional-programming


【解决方案1】:

参数不是Array,它是一个Object,有点像数组。

if(arguments.length > 0) { // Slow AND superfluous
    for (var i = 0; i < arguments.length; i++) { // Even SLOWER
        arguments[i]; // Holy...

缓存长度,访问属性很慢,IE6 对.length 根本没有优化,我什至怀疑使用arguments[i] 时它真的很慢,因为它不是真正的Array,因此可能会进行未优化的属性查找。

如果您想两全其美,请传递普通的Array,使用普通的for 循环,然后cache length

function ie6PNGFixLoader(scripts) {
    for (var i = 0, l = scripts.length; i < l; i++) {
        $.ajax({// load PNG fix scripts
            url: scripts[i],
            cache: true,
            dataType: 'script'
        });
    }              
}

ie6PNGFixLoader(["/Global/ICIS/Scripts/DD_belatedPNG_0.0.8a-min.js",
                 "/Global/ICIS/Scripts/DD_PNG_listing.js"]);

编辑

说清楚一点,给循环计时是没用的,请求是异步的,你所做的只是计时一个循环和一个对$.ajax的调用,这里没有优化的意义,尤其是对于两个 条目。即使在 IE6 中,执行 Ajax 调用本身(即使只是调用 $.ajax)也会比循环慢得多。

【讨论】:

  • @Anders 那又怎样,为什么要投反对票?是否愿意发布一个不包含 arguments 的大型性能测试?
  • @Anders 如果您抱怨我不推荐while(--i),并且可以在我的回答中抱怨过早优化,我所说的只是if you want the best of both words。除此之外,循环几乎不是这里的限制因素...... Ajax 将花费更多时间。
  • @Ivo Wetzel,我只发布了一个关于循环条件及其性能的链接,因为你在谈论它。认为这可能对 OP 有用。
  • +1。虽然您可以执行诸如while(--i)for (i=0; node = array[i++];) 之类的复杂操作并获得一小部分微秒,但您会失去最重要的东西,即可读性。 @Ivo 显示的 for 循环是干净的、可读的,并且地球上几乎每个开发人员都可以理解。除非绝对必要,否则对可读性进行微优化是没有意义的。而且由于$.ajax 调用无论如何都会占主导地位,这是一个有争议的问题。
  • 哦,如果您需要按正序迭代,那会想到另一件事,while(--i) 是没用的。