为什么这段代码的执行速度如此不同?

时间:2011-01-14 22:20:31

标签: javascript jquery

Internet Explorer 7 中,此代码在 47 ms中始终如一地执行:

function updateObjectValues() {    
    $('.objects').html(12345678); // ~500 DIVs
}

但是,此代码在 157 ms:

中始终如一地执行
function updateObjectValues() {
    $('.objects').html('12345678'); // ~500 DIVs
}

传递数字比字符串快3倍。为什么这些结果如此显着不同?并且,有没有办法帮助字符串的性能?

4 个答案:

答案 0 :(得分:9)

如果你看一下jQuery源代码(甚至是未公开的生产版本),你会发现代码的if (typeof value === "string" ...分支显着比final {更复杂}传入号码时会发生的{1}}版本。

这是1.4.4代码,如果值是一个字符串:

else

以下是数字的作用:

} else if ( typeof value === "string" && !rnocache.test( value ) &&
    (jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) &&
    !wrapMap[ (rtagName.exec( value ) || ["", ""])[1].toLowerCase() ] ) {

    value = value.replace(rxhtmlTag, "<$1></$2>");

    try {
        for ( var i = 0, l = this.length; i < l; i++ ) {
            // Remove element nodes and prevent memory leaks
            if ( this[i].nodeType === 1 ) {
                jQuery.cleanData( this[i].getElementsByTagName("*") );
                this[i].innerHTML = value;
            }
        }

    // If using innerHTML throws an exception, use the fallback method
    } catch(e) {
        this.empty().append( value );
    }
}

显然,所有这些额外检查和函数调用的开销加起来。我的意思是,即使只是在顶部的} else { this.empty().append( value ); } 语句中,也有三个正则表达式测试,一个地图查找和一个小写的字符串 - 这是在我们进入之前语句的主体(如果我们这样做,也许其中一个检查返回if),这涉及进一步的正则表达式(作为参数化替换的一部分)和循环......

答案 1 :(得分:3)

我刚刚进行了测试,似乎证实了我原来的观念:

.text(string).html(number)一样快,.html(string)

中必须有字符串解析开销

这个开销是在ie7还是在jQuery中我不清楚。 Ie8似乎没有同样的问题,这表明问题不是我的jQuery,但是ie8有一个比ie7更快的js引擎......

答案 2 :(得分:2)

数字可以二进制存储,可能存储在一个寄存器中。字符串必须在内存中以字符串形式存储。因此,优化解释器或JIT编译器将利用整数提供的可能速度。

另外,正如Martin Jespersen所指出的那样,html()函数可以处理不同于数字的字符串,在它上面执行更多工作 - 如果它知道差异的话。感谢马丁在那里。

答案 3 :(得分:1)

作为T.J. Crowder指出,查看the source会发现字符串的代码路径完全不同;具有讽刺意味的是,相关的评论表明,这是为了利用“捷径”:

html: function( value ) {
        if ( value === undefined ) {
            return this[0] && this[0].nodeType === 1 ?
                this[0].innerHTML.replace(rinlinejQuery, "") :
                null;

        // See if we can take a shortcut and just use innerHTML
        } else if ( typeof value === "string" && !rnocache.test( value ) &&
            (jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) &&
            !wrapMap[ (rtagName.exec( value ) || ["", ""])[1].toLowerCase() ] ) {

            value = value.replace(rxhtmlTag, "<$1></$2>");

            try {
                for ( var i = 0, l = this.length; i < l; i++ ) {
                    // Remove element nodes and prevent memory leaks
                    if ( this[i].nodeType === 1 ) {
                        jQuery.cleanData( this[i].getElementsByTagName("*") );
                        this[i].innerHTML = value;
                    }
                }

            // If using innerHTML throws an exception, use the fallback method
            } catch(e) {
                this.empty().append( value );
            }

        } else if ( jQuery.isFunction( value ) ) {
            this.each(function(i){
                var self = jQuery( this );

                self.html( value.call(this, i, self.html()) );
            });

        } else {
            this.empty().append( value );
        }

        return this;
    },
相关问题