eval的兩組性能測(cè)試數(shù)據(jù)
引發(fā)了最近對(duì)eval火爆的討論,教主 @Franky 和 灰大 @otakustay 也給了精彩的數(shù)據(jù)分析。
剛好之前也做過類似的測(cè)試,我也跟風(fēng)湊個(gè)熱鬧,提供兩組數(shù)據(jù)供大家參考。
更新1: 感謝灰大 @otakustay 的指導(dǎo),為排除eval('')調(diào)用本身對(duì)結(jié)果的影響,增加一組新數(shù)據(jù)A3, B3。并對(duì)舊的全部數(shù)據(jù)重測(cè)。
更新2: 感謝莫大 @貘吃饃香 的強(qiáng)力拍磚,增加了1). A4, B4;A5,B5的eval覆蓋后的測(cè)試數(shù)據(jù); 2). A6,B6 eval別名;3). A7,B7 eval.call。
測(cè)試環(huán)境:
a. 機(jī)器:Intel(R) Corei7-2720 2.2Ghz (4核心8線程)、內(nèi)存8Gb
b. OS:Windows 7 Enterprise SP1 64-bit
c. 瀏覽器:
b.1 Google Chrome 21.0.1180.79 m
b.2 Firefox 14.0.1
b.3 IE9.0.8112.16421
d. 測(cè)試方法
d.1 每個(gè)用例測(cè)試5次,耗時(shí)取最小值。
d.2 測(cè)試過程中沒有開啟Firebug或Chrome Console,開啟這些工具會(huì)使時(shí)間倍增,很難在有效時(shí)間內(nèi)得到該用例結(jié)果
用例A1:
我們?cè)趦?nèi)聯(lián)函數(shù)中調(diào)用空的eval("")
!function() {
var a = 1,
b = 2,
c = true;
function func() {
var d = 2;
e = !c;
eval("");
}
for (var i = 0; i < 2999999; i++) {
func(i, i + 1, i + 2);
}
}();
用例A2:
注釋掉內(nèi)聯(lián)函數(shù)中的eval("")
!function() {
var a = 1,
b = 2,
c = true;
function func() {
var d = 2;
e = !c;
//eval("");
}
for (var i = 0; i < 2999999; i++) {
func(i, i + 1, i + 2);
}
}();
用例A3:
為排除eval("")調(diào)用本身產(chǎn)生的影響,我們?cè)谕鈱雍瘮?shù)中調(diào)用eval("")
!function() {
var a = 1,
b = 2,
c = true;
function func() {
var d = 2;
e = !c;
}
for (var i = 0; i < 2999999; i++) {
eval("");
func(i, i + 1, i + 2);
}
}();
用例A4:
將eval()函數(shù)覆蓋成普通的空函數(shù)
function eval(){}
!function() {
var a = 1,
b = 2,
c = true;
function func() {
var d = 2;
e = !c;
eval("");
}
for (var i = 0; i < 2999999; i++) {
func(i, i + 1, i + 2);
}
}();
用例A5:
同樣是函數(shù)調(diào)用,不是eval而且另一個(gè)空函數(shù)f
function f(){}
!function() {
var a = 1,
b = 2,
c = true;
function func() {
var d = 2;
e = !c;
f("");
}
for (var i = 0; i < 2999999; i++) {
func(i, i + 1, i + 2);
}
}();
用例A6:
將eval賦給另一個(gè)變量f,然后調(diào)用f
var f = eval;
!function() {
var a = 1,
b = 2,
c = true;
function func() {
var d = 2;
e = !c;
f("");
}
for (var i = 0; i < 2999999; i++) {
func(i, i + 1, i + 2);
}
}();
用例A7:
使用eval.call的方式去調(diào)用
!function() {
var a = 1,
b = 2,
c = true;
function func() {
var d = 2;
e = !c;
eval.call(null, '');
}
for (var i = 0; i < 2999999; i++) {
func(i, i + 1, i + 2);
}
}();
A組測(cè)試結(jié)果:
A1 | A2 | A3 | A4 | A5 | A6 | A7 | A1 : A2 | A1 : A3 | A1 : A4 | A4 : A5 | |
Chrome | 1612ms | 8ms | 1244ms | 897ms | 7ms | 718ms | 680ms | 201.5 | 1.3 | 1.8 | 128.1 |
Firefox | 2468ms | 69ms | 732ms | 2928ms | 134ms | 5033ms | 4984ms | 35.8 | 3.4 | 0.8 | 21.9 |
IE | 1207ms | 23ms | 233ms | 1147ms | 37ms | 148ms | 224ms | 52.5 | 5.2 | 1.0 | 31.0 |
for (var i = 0; i < 2999999; i++) {
!function() {
var a = 1,
b = 2,
c = true;
!function () {
var d = 2;
e = !c;
eval("");
}();
}();
}
用例B2:
for (var i = 0; i < 2999999; i++) {
!function() {
var a = 1,
b = 2,
c = true;
!function () {
var d = 2;
e = !c;
//eval("");
}();
}();
}
用例B3:
for (var i = 0; i < 2999999; i++) {
!function() {
var a = 1,
b = 2,
c = true;
!function () {
var d = 2;
e = !c;
}();
}();
eval("");
}
用例B4:
var eval = function(){}
for (var i = 0; i < 2999999; i++) {
!function() {
var a = 1,
b = 2,
c = true;
!function () {
var d = 2;
e = !c;
eval("");
}();
}();
}
用例B5:
var f = function(){}
for (var i = 0; i < 2999999; i++) {
!function() {
var a = 1,
b = 2,
c = true;
!function () {
var d = 2;
e = !c;
f("");
}();
}();
}
用例B6:
var f = eval;
for (var i = 0; i < 2999999; i++) {
!function() {
var a = 1,
b = 2,
c = true;
!function () {
var d = 2;
e = !c;
f("");
}();
}();
}
用例B7:
for (var i = 0; i < 2999999; i++) {
!function() {
var a = 1,
b = 2,
c = true;
!function () {
var d = 2;
e = !c;
eval.call(null, '');
}();
}();
}
B組測(cè)試結(jié)果:
B1 | B2 | B3 | B4 | B5 | B6 | B7 | B1 : B3 | B1 : B2 | B1 : B4 | B4 : B5 | |
Chrome | 1569ms | 134ms | 1093ms | 1022ms | 173ms | 830ms | 916ms | 11.7 | 1.4 | 1.5 | 5.9 |
Firefox | 5334ms | 1017ms | 5503ms | 5280ms | 1171ms | 6797ms | 6883ms | 5.2 | 1.0 | 1.0 | 4.5 |
IE | 3933ms | 560ms | 680ms | 4118ms | 583ms | 745ms | 854ms | 7.0 | 5.8 | 1.0 | 111.3 |
結(jié)論(僅限于文中的CASE):
1. eval本身的重復(fù)調(diào)用非常耗時(shí),即使是空的eval("");
2. eval對(duì)內(nèi)聯(lián)函數(shù)執(zhí)行效率有所影響,依具體環(huán)境、代碼有所不同;
3. 我們可以看到無(wú)論哪種瀏覽器,無(wú)論是A組還是B組,2 和 5速度較佳。說(shuō)明例中內(nèi)聯(lián)函數(shù)的eval無(wú)論以何種方式調(diào)用(即使eval被空函數(shù)覆蓋)仍會(huì)對(duì)運(yùn)行效率造成較大影響。推斷是(黑盒推斷,非權(quán)威,很可能是臆測(cè))內(nèi)聯(lián)函數(shù)中只要發(fā)現(xiàn)eval,哪怕這個(gè)eval是被覆蓋的空函數(shù),在Scope Variables中都將會(huì)把所有的外部定義的變量等內(nèi)容初始化到當(dāng)前的Scope中。類似的,eval會(huì)對(duì)內(nèi)聯(lián)函數(shù)在運(yùn)行時(shí)JS引擎的優(yōu)化功能產(chǎn)生較大影響,降低執(zhí)行效率。
4. 說(shuō)點(diǎn)題外話,雖然沒用IE10,而是IE9,在對(duì)eval的處理上,表現(xiàn)非常的優(yōu)異。IE一直被開發(fā)人員詬病,但它的飛速成長(zhǎng)也是值得肯定的,本例就是很好的一項(xiàng)證明。
更詳細(xì)的原因剖析下列文章描述已十分詳細(xì),不再累述。歡迎拍磚:)尤其是莫大...
@老趙 的 《由eval生成的代碼效率真的很差嗎?》
@Franky 的 《Eval科普》
@otakustay 的 《淺談Eval的影響》
相關(guān)文章
javascript html5實(shí)現(xiàn)表單驗(yàn)證
這篇文章主要為大家詳細(xì)介紹了javascript html5實(shí)現(xiàn)表單驗(yàn)證的具體代碼,感興趣的小伙伴們可以參考一下2016-03-03JS采用絕對(duì)定位實(shí)現(xiàn)回到頂部效果完整實(shí)例
這篇文章主要介紹了JS采用絕對(duì)定位實(shí)現(xiàn)回到頂部效果,以完整實(shí)例形式分析了JS定位到頁(yè)面頂部功能的實(shí)現(xiàn)方法,涉及javascript動(dòng)態(tài)操作頁(yè)面元素與屬性的相關(guān)技巧,需要的朋友可以參考下2016-06-06Axios設(shè)置token請(qǐng)求頭的三種方式
用戶登錄時(shí),后端會(huì)返回一個(gè)token,并且保存到瀏覽器的localstorage中,可以根據(jù)localstorage中的token判斷用戶是否登錄,所以當(dāng)發(fā)送請(qǐng)求時(shí),都要攜帶token給后端進(jìn)行判斷,本文給大家介紹了Axios設(shè)置token請(qǐng)求頭的三種方式,需要的朋友可以參考下2024-02-02基于JavaScript構(gòu)建一個(gè)動(dòng)態(tài)博客應(yīng)用
這篇文章主要為大家詳細(xì)介紹了如何基于JavaScript構(gòu)建一個(gè)動(dòng)態(tài)博客應(yīng)用,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-02-02JavaScript html5利用FileReader實(shí)現(xiàn)上傳功能
這篇文章主要為大家詳細(xì)介紹了JavaScript html5利用FileReader實(shí)現(xiàn)上傳功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-03-03JS表單提交驗(yàn)證、input(type=number) 去三角 刷新驗(yàn)證碼
在進(jìn)行表單提交時(shí),需要對(duì)輸入框和文本域等的value的合理性進(jìn)行驗(yàn)證,可以編寫form的onSubmit事件,下面給大家介紹js表單提交驗(yàn)證input(type=number) 去三角 刷新驗(yàn)證碼注意事項(xiàng),一起看看吧2017-06-06