在 Internet Explorer 7 中,此代码在 47 ms中始终如一地执行:
function updateObjectValues() {
$('.objects').html(12345678); // ~500 DIVs
}
但是,此代码在 157 ms:
中始终如一地执行function updateObjectValues() {
$('.objects').html('12345678'); // ~500 DIVs
}
传递数字比字符串快3倍。为什么这些结果如此显着不同?并且,有没有办法帮助字符串的性能?
答案 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;
},