欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Javascript中八種遍歷方法的執(zhí)行速度深度對(duì)比

 更新時(shí)間:2017年04月25日 09:40:16   作者:路易斯  
關(guān)于數(shù)組或?qū)ο蟊闅v,相信很多人都沒有深入觀察過執(zhí)行效率。這是一個(gè)曾在群里吵翻天的話題,讀懂后你將成為遍歷效率話題的大師。下面這篇文章主要介紹了Javascript中八種遍歷方法執(zhí)行速度深度對(duì)比的相關(guān)資料,需要的朋友可以參考下。

前言

遍歷數(shù)組或?qū)ο笫且幻绦騿T的基本素養(yǎng)之一. 然而遍歷卻不是一件簡(jiǎn)單的事, 優(yōu)秀的程序員知道怎么去選擇合適的遍歷方法, 優(yōu)化遍歷效率. 本篇將帶你走進(jìn)JavaScript遍歷的世界, 享受分析JS循環(huán)的快感. 本篇所有代碼都可以直接運(yùn)行, 希望您通讀本篇后, 不止是瀏覽, 最好是親手去實(shí)踐下.

概述

js有如下兩種數(shù)據(jù)需要經(jīng)常遍歷

  • 數(shù)組(Array)
  • 對(duì)象(Object)

同時(shí)又提供了如下8種方法方便我們遍歷元素

  • for
  • while(或do~while)
  • forEach
  • for in
  • $.each
  • $(selecter).each
  • map
  • every

最終我們將分析遍歷效率選出最佳遍歷選手.

本文將針對(duì)如下兩種數(shù)據(jù)進(jìn)行詳細(xì)的分析和舉栗. 下面舉栗中如果不加特殊說明將會(huì)用到如下數(shù)據(jù).

var array = ["囚徒","過客","領(lǐng)袖"];//職場(chǎng)3種人
var o = {0:"linda",1:"style",2:"nick",length:3};

for

語(yǔ)法: for(初始化; 循環(huán)執(zhí)行條件; 每遍歷一個(gè)元素后做的事情;){}

(function(){//循環(huán)置于閉包之內(nèi)
 for(var i=0,length=array.length;i<length;i++){//緩存數(shù)組長(zhǎng)度
 console.log(array[i]);//內(nèi)部方法若有可能相互影響,也要置于閉包之內(nèi)
 }
})();

for循環(huán)只能遍歷數(shù)組, 不能遍歷對(duì)象. 寫for循環(huán)時(shí)有兩點(diǎn)需要注意.

  • 其一, 為了避免遍歷時(shí)執(zhí)行多遍計(jì)算數(shù)組長(zhǎng)度的操作, 影響效率, 建議在循環(huán)開始以變量的形式緩存下數(shù)組長(zhǎng)度, 若在循環(huán)內(nèi)部有可能改變數(shù)組長(zhǎng)度, 請(qǐng)務(wù)必慎重處理, 避免數(shù)組越界.
  • JavaScript中并沒有類似java的塊級(jí)作用域, for循環(huán)內(nèi)部定義的變量會(huì)直接暴露在外(如 i,循環(huán)退出后,i變量將等于數(shù)組長(zhǎng)度, 后續(xù)代碼將能訪問到 i 變量的值), 因此建議將for循環(huán)置于閉包內(nèi). 特別要注意的是: 如果在循環(huán)內(nèi)部, 前一個(gè)元素的遍歷有可能影響到后一個(gè)元素的遍歷, 那么for循環(huán)內(nèi)部方法也需要置于閉包之內(nèi).

do/while

語(yǔ)法: do{...}while(true);

 do while
(function() {
 var i = 0,
 len = array.length;
 do {
 if (i == 2) {
 break; // 循環(huán)被終止, 此處如果是continue就會(huì)造成循環(huán)無(wú)法退出
 };
 console.log('array['+ i +']:' + array[i]);
 i++;//此句建議放置循環(huán)while頭部
 } while(i<len);
})();

do/while的語(yǔ)法簡(jiǎn)化了循環(huán)的實(shí)現(xiàn), 只保留對(duì)循環(huán)條件的判斷, 所以我們要在循環(huán)內(nèi)部構(gòu)造出循環(huán)退出的條件, 否則有可能造成死循環(huán). 特別要注意的是: 使用 continue 跳出本次遍歷時(shí), 要保證循環(huán)能夠自動(dòng)進(jìn)入到下一次遍歷, 因此保證循環(huán)走到下一次遍歷的語(yǔ)句需要放到 continue 前面執(zhí)行, 建議置于循環(huán)頭部.(如上, i++ 語(yǔ)句最好放置循環(huán)頭部)

do/while 循環(huán)與for循環(huán)大體差不多,只支持?jǐn)?shù)組遍歷, 多用于對(duì)循環(huán)退出條件不是很明確的場(chǎng)景. 一般來(lái)說不建議使用這種方式遍歷數(shù)組.

forEach

語(yǔ)法: array.forEach(function(item){}) , 參數(shù)item表示數(shù)組每一項(xiàng)的元素

array.forEach(function(item){
 if(item=="囚徒")
 return;//這里只能使用return跳過當(dāng)前元素處理
 console.log(item);
});

forEach回調(diào)function默認(rèn)有三個(gè)參數(shù): item, index, array.

使用forEach循環(huán)有幾點(diǎn)需要特別注意:

  • forEach無(wú)法遍歷對(duì)象
  • forEach無(wú)法在IE中使用,只是在firefox和chrome中實(shí)現(xiàn)了該方法
  • forEach無(wú)法使用break,continue跳出循環(huán),使用return時(shí),效果和在for循環(huán)中使用continue一致

for in

語(yǔ)法: for(var item in array){}

for(var item in array){
 console.log(item);
}//0 1 2
for(var item in o){
 console.log(item);
}//0 1 2 length

for in 可用于遍歷數(shù)組和對(duì)象, 但它輸出的只是數(shù)組的索引和對(duì)象的key, 我們可以通過索引和key取到對(duì)應(yīng)的值. 如下:

for(var item in array){
 console.log(array[item]);
}//"囚徒" "過客" "領(lǐng)袖"
for(var item in o){
 console.log(o[item]);
}//"linda" "style" "nick" "length"

$.each

語(yǔ)法: $.each(array|o, function(i, ele){}) 支持?jǐn)?shù)組和對(duì)象

$.each(array, function(i, ele){
 console.log(i,ele,this==ele);
});
//0 "囚徒" true
//1 "過客" true
//2 "領(lǐng)袖" true
$.each(o, function(i, ele){
 console.log(i,ele,this==ele);
});
//0 "linda" true
//1 "style" true
//2 "nick" true

這里我們注意到 this對(duì)象 指向當(dāng)前屬性的值,這是因?yàn)?

參考jQuery api:

$.each() 方法會(huì)迭代jQuery對(duì)象中的每一個(gè)DOM元素。每次回調(diào)函數(shù)執(zhí)行時(shí),會(huì)傳遞當(dāng)前循環(huán)次數(shù)作為參數(shù)(從0開始計(jì)數(shù))。更重要的是,回調(diào)函數(shù)是在當(dāng)前DOM元素為上下文的語(yǔ)境中觸發(fā)的。因此關(guān)鍵字 this 總是指向這個(gè)元素。
同時(shí),上述遍歷時(shí), o 對(duì)象的屬性中有一個(gè)length屬性并沒有被輸出. 這是為什么呢? 請(qǐng)耐心往下看.

首先, 我們來(lái)看看遍歷對(duì)象o時(shí), 當(dāng)前的this對(duì)象到底是什么?

$.each(o, function(i, ele){
 if(this=="linda"){//我們隨機(jī)選取第一個(gè)屬性
 console.log(this,this==ele);
 $.each(this, function(e, ele2) {
 console.log(e, ele2);
 });
 }
});
//String {0: "l", 1: "i", 2: "n", 3: "d", 4: "a", length: 5, [[PrimitiveValue]]: "linda"} true
//0 "l"
//1 "i"
//2 "n"
//3 "d"
//4 "a"

我們發(fā)現(xiàn), this對(duì)象等于回調(diào)函數(shù)的第二個(gè)形參. 且它的 length 屬性和 [[PrimitiveValue]] 屬性并沒有被打印出來(lái), 為此我們來(lái)查看下length的內(nèi)部屬性.

$.each(o, function(i, ele){
 if(this=="linda")//我們還是隨機(jī)選取第一個(gè)屬性(這還是隨機(jī)嗎?)
 console.log(Object.getOwnPropertyDescriptor(this, 'length'));
});
//Object {value: 5, writable: false, enumerable: false, configurable: false}

可見, this對(duì)象的length屬性的 enumerable 屬性被設(shè)置成了false, 這表示該對(duì)象不能被列舉或遍歷, 同時(shí)還不能被配置(configurable: false) , 也不能被賦值(writable: false) .

此時(shí), 前面遍歷 o 對(duì)象時(shí),它的 length 屬性沒有被打印出來(lái)的疑問似乎有解了. 讓我們來(lái)看看 o.length 的內(nèi)部屬性吧.

console.log(Object.getOwnPropertyDescriptor(o, 'length'));
//Object {value: 3, writable: true, enumerable: true, configurable: true}

o.length 值為3, 可賦值, 可列舉, 可配置. 這可不對(duì), 剛剛不是說 enumerable 屬性被設(shè)置成了false 才不會(huì)被遍歷嗎. 現(xiàn)在該值為 true, 并且還不可遍歷. 這不合常理, 自然該有別的原因. 我們接著往下看.

var o = {0:"linda",1:"style",2:"nick",length:1}; // 試著改變length的值
$.each(o, function(i, ele){//再遍歷一次
 console.log(i,ele);
});
//0 "linda"

var o = {0:"linda",1:"style",2:"nick",length:5}; // 堅(jiān)持改變length的值
$.each(o, function(i, ele){//再遍歷一次
 console.log(i,ele);
});
// 0 linda
// 1 style
// 2 nick
// length 5

var o = {0:"linda",1:"style",2:"nick"}; // 試試去掉length屬性
$.each(o, function(i, ele){//再遍歷一次
 console.log(i,ele);
});
// 0 linda
// 1 style
// 2 nick

現(xiàn)象明了, 結(jié)合jquery源碼, 當(dāng)對(duì)象中存在length屬性時(shí), $.each 內(nèi)部使用for循環(huán)去遍歷對(duì)象, 否則它將使用for in循環(huán)去遍歷, 因此$.each遍歷對(duì)象遵循如下規(guī)律:

  • 如果對(duì)象中存在 length 屬性, 遍歷深度以length屬性為準(zhǔn), 即length多大, 遍歷多少個(gè)元素.
  • 如果對(duì)象中不存在 length 屬性, 遍歷深度以實(shí)際內(nèi)部屬性個(gè)數(shù)為準(zhǔn).

不僅如此, $.each的具體使用過程中還有以下幾點(diǎn)需要注意:

  • 使用 return 或者 return true 為跳過一個(gè)元素,繼續(xù)執(zhí)行后面的循環(huán);
  • 使用 return false 為終止循環(huán)的執(zhí)行, 這是因?yàn)樵?jquery.each 中, 若返回值指定為false, 才跳出循環(huán), 如果感興趣請(qǐng)翻看 jquery.each 源碼;
  • 無(wú)法使用 break 與 continue 來(lái)跳過循環(huán).

$(selecter).each

語(yǔ)法: $(selecter|array|o).each(function(i, ele){}) 支持?jǐn)?shù)組和對(duì)象, 該方法基本上與$.each方法相同.

$('div').each(function(i,ele){
 console.log(this,i,this == ele);
});
//dom... 0 dom.... true
$(array).each(function(i,ele){//處理數(shù)組
 if(this == "領(lǐng)袖")
 console.log(this,i,this == ele);
});
//String {0: "領(lǐng)", 1: "袖", length: 2, [[PrimitiveValue]]: "領(lǐng)袖"} 2 true
$(o).each(function(i,ele){//處理對(duì)象
 if(this == "nick")
 console.log(this,i,this == ele);
});
//String {0: "n", 1: "i", 2: "c", 3: "k", length: 4, [[PrimitiveValue]]: "nick"} 2 true

dom表示div元素, 由于this恒等ele, 說明this也表示div元素, 所以this并不是jquery對(duì)象, 而是普通的DOM對(duì)象(可以在this上隨意使用DOM方法). 使用$(selecter).each方法,請(qǐng)注意以下幾點(diǎn):

  • i: 即序列值 ele: 表示當(dāng)前被遍歷的DOM元素
  • this 表示當(dāng)前被遍歷的DOM元素,不能調(diào)用jQuery方法, 如需調(diào)用jquery方法需要用$符號(hào)包裹.如, $(this)

map

Array.prototype.map,該方法只支持?jǐn)?shù)組

語(yǔ)法: array.map(callback[,thisArg]) map方法使用其提供函數(shù)的每次返回結(jié)果生成一個(gè)新的數(shù)組.

var array = [1, 4, 9];
var roots = array.map(Math.sqrt);//map包裹方法名
// roots is now [1, 2, 3], array is still [1, 4, 9]
var array = [1, 4, 9];
var doubles = array.map(function(num) {//map包裹方法實(shí)體
 return num * 2;
});
// doubles is now [2, 8, 18]. array is still [1, 4, 9]

實(shí)際上,由于map方法被設(shè)計(jì)成支持 [鴨式辨型][] , 該方法也可以用來(lái)處理形似數(shù)組的對(duì)象, 例如 NodeList.

var elems = document.querySelectorAll('select option:checked');
var values = Array.prototype.map.call(elems, function(obj) {
 return obj.value;
});

甚至還可以用來(lái)處理字符串, 如下:

var map = Array.prototype.map;
var array = map.call('Hello 中國(guó)', function(x) { 
 return x.charCodeAt(0);
});
console.log(array);
//[72, 101, 108, 108, 111, 32, 20013, 22269]

map處理字符串的方式多種多樣, 例如 反轉(zhuǎn)等.

var str = '12345';
var output = Array.prototype.map.call(str, function(x) {
 return x;
}).reverse().join('');
console.log(output);//54321

例如 將字符串?dāng)?shù)組轉(zhuǎn)換為數(shù)字?jǐn)?shù)組, 只需一條語(yǔ)句, 如下:

console.log(['1', '2', '3'].map(Number));//[1,2,3]

目前map方法被大部分瀏覽器支持, 除了IE 6,7,8.

every

Array.prototype.every, 該方法同上述map方法也只支持?jǐn)?shù)組

語(yǔ)法: arr.every(callback[, thisArg]) every 方法用于檢驗(yàn)數(shù)組中的每一項(xiàng)是否符合某個(gè)條件, 若符合則放回true, 反之則返回false.

function isBigEnough(element, index, array) {
 return element >= 10;
}
[12, 5, 8, 130, 44].every(isBigEnough); // false
[12, 54, 18, 130, 44].every(isBigEnough); // true

該方法還有簡(jiǎn)寫方式, 如下:

[12, 5, 8, 130, 44].every(elem => elem >= 10); // false
[12, 54, 18, 130, 44].every(elem => elem >= 10); // true

以上, 遍歷數(shù)組和對(duì)象的8種方法簡(jiǎn)單的介紹完, 小結(jié)如下:

  • for in , $.each , $().each 既支持對(duì)象也支持?jǐn)?shù)組遍歷;
  • for , do/while , forEach 只支持?jǐn)?shù)組;
  • Array.prototype.map, Array.prototype.every 只支持?jǐn)?shù)組和形似數(shù)組的對(duì)象;
  • forEach不能退出循環(huán),只能通過return來(lái)進(jìn)入到下一個(gè)元素的遍歷中(相當(dāng)于for循環(huán)的continue), 且在IE沒有實(shí)現(xiàn)該方法;
  • $.each和$().each循環(huán)只能通過return false 來(lái)退出循環(huán), 使用return 或 return true 將跳過一個(gè)元素, 繼續(xù)執(zhí)行后面的循環(huán).

測(cè)試各方法效率

下面我們來(lái)測(cè)試下上述方法的效率.

注: array數(shù)組默認(rèn)為空, 依次賦值數(shù)組長(zhǎng)度為1 000 000, 10 000 000, 100 000 000, 分別在 Chrome, Firefox, Safari 瀏覽器上進(jìn)行兩輪測(cè)試, 取測(cè)試時(shí)間平均值作為比較對(duì)象, 時(shí)間單位為ms. 如下是測(cè)試代碼:

var array = [],
 length = array.length = 10000000;//(一千萬(wàn))
//for(var i=0;i<length;i++){
// array[i] = 'louis';
//}
console.log(array[0]);
//-------------------------for
var t1 = +new Date();
for(var i=0;i<length;i++){
}
var t2 = +new Date();
console.log('for:' + (t2-t1));

//-------------------------do/while
var t1 = +new Date();
var i = 0;
do {
 i++;
} while(i<length);
var t2 = +new Date();
console.log('do while:' + (t2-t1));

//-------------------------forEach
var t1 = +new Date();
array.forEach(function(item){
});
var t2 = +new Date();
console.log('forEach:' + (t2-t1));

//-------------------------for in
var t1 = +new Date();
for(var item in array){
}
var t2 = +new Date();
console.log('for in:' + (t2-t1));

//------------------------- $.each
var t1 = +new Date();
$.each(array, function(i, ele){
});
var t2 = +new Date();
console.log('$.each:' + (t2-t1));

//-------------------------$().each
var t1 = +new Date();
$(array).each(function(i,ele){
});
var t2 = +new Date();
console.log('$(ele).each:' + (t2-t1));

//-------------------------map
var t1 = +new Date();
array.map(function(num){
});
var t2 = +new Date();
console.log('map:' + (t2-t1));

//-------------------------every
var t1 = +new Date();
array.every(function(e,i,arr){
});
var t2 = +new Date();
console.log('every:' + (t2-t1));

測(cè)試機(jī)器正常運(yùn)行 IDE, 編輯器, 瀏覽器, qq, 微信等常用應(yīng)用, 系統(tǒng)空閑. 硬件設(shè)備如下:

  • 操作系統(tǒng): OSX EI Capitan 版本 10.11.5
  • MacBook Pro(13 英寸,2015 年初期)
  • 處理器: 2.7 GHz Intel Core i5
  • 內(nèi)存: 8 GB 1867 MHz DDR3

以上多輪測(cè)試結(jié)果匯總?cè)缦氯龔埍?單位:ms):

數(shù)組長(zhǎng)度為10^6


數(shù)組長(zhǎng)度為10^6 chrome 52.0.2743.116 (64-bit) Firefox Developer Edition 49.0a2 (2016-08-01) Safari 9.1.1 (11601.6.17)
for (16+19)/2 = 17.5 (6+7)/2 = 6.5 (6+7)/2 = 6.5
do while (24+17)/2 = 20.5 (7+5)/2 = 6 (5+5)/2 = 5
for in (19+28)/2 = 23.5 (0+0)/2 = 0 (0+0)/2 = 0
forEach (41+28)/2 = 34.5 (4+4)/2 = 4 (31+29)/2 = 30
map (26+32)/2 = 28 (4+4)/2 = 4 (32+26)/2 = 28
every (22+24)/2 = 23 (4+5)/2 = 4.5 (41+45)/2 = 43
$.each (29+27)/2 = 28 (306+311)/2 = 308.5 (111+97)/2 = 104
$(e).each (94+98)/2 = 96 (484+488)/2 = 486 (79+64)/2 = 71.5

數(shù)組長(zhǎng)度為10^7


數(shù)組長(zhǎng)度為10^7 chrome 52.0.2743.116 (64-bit) Firefox Developer Edition 49.0a2 (2016-08-01) Safari 9.1.1 (11601.6.17)
for (164+161)/2 = 162.5 (26+30)/2 = 28 (30+31)/2 = 30.5
do while (163+157)/2 = 160 (27+25)/2 = 26 (28+27)/2 = 27.5
for in (78+86)/2 = 82 (0+0)/2 = 0 (0+0)/2 = 0
forEach (211+205)/2 = 208 (31+30)/2 = 30.5 (291+289)/2 = 290
map (349+282)/2 = 315.5 (24+22)/2 = 23 (259+260)/2 = 259.5
every (221+219)/2 = 220 (24+24)/2 = 24 (251+257)/2 = 254
$.each (210+215)/2 = 212.5 (2868+2789)/2 = 2828.5 (699+724)/2 = 711.5
$(e).each (730+669)/2 = 699.5 (4674+4722)/2 = 4698 (523+546)/2 = 534.5

數(shù)組長(zhǎng)度為10^8


數(shù)組長(zhǎng)度為10^8 chrome 52.0.2743.116 (64-bit) Firefox Developer Edition 49.0a2 (2016-08-01) Safari 9.1.1 (11601.6.17)
for (1486+1583)/2 = 1534.5 (222+238)/2 = 230 (261+251)/2 = 256
do while (1548+1608)/2 = 1578 (236+247)/2 = 241.5 (272+265)/2 = 268.5
for in (0+0)/2 = 0 (0+0)/2 = 0 (0+0)/2 = 0
forEach (25838+22307)/2 = 24072.5 (212+209)/2 = 210.5 (2565+2568)/2 = 2566.5
map (23795+22787)/2 = 23291 (215+206)/2 = 210.5 (2556+2573)/2 = 2564.5
every (22393+22378)/2 = 22385.5 (212+215)/2 = 213.5 (2550+2548)/2 = 2549
$.each (14523+14776)/2 = 14649.5 (28007+27698)/2 = 27852.5 (7109+7156)/2 = 7132.5
$(e).each chrome 奔潰了... (49352+49530)/2 = 49441 (5505+4616)/2 = 5060.5

綜上, 我們發(fā)現(xiàn)for in 循環(huán)的性能不穩(wěn)定, 猜測(cè)它可能沒有進(jìn)入循環(huán). 因此將數(shù)組各元素進(jìn)行如下賦值. 重新進(jìn)行如下兩輪測(cè)試.

var array = [],
 length = array.length = 1000000;
for(var i=0;i<length;i++){
 array[i] = 'louis';
}

數(shù)組賦值后, 數(shù)組長(zhǎng)度為10^6


數(shù)組長(zhǎng)度為10^6 chrome 52.0.2743.116 (64-bit) Firefox Developer Edition 49.0a2 (2016-08-01) Safari 9.1.1 (11601.6.17)
for (21+22)/2 = 21.5 (8+10)/2 = 9 (6+5)/2 = 5.5
do while (22+19)/2 = 20.5 (6+6)/2 = 6 (6+5)/2 = 5.5
for in (178+184)/2 = 181 (318+268)/2 = 293 (413+464)/2 = 438.5
forEach (42+45)/2 = 43.5 (4+4)/2 = 4 (21+24)/2 = 22.5
map (137+153)/2 = 145 (9+8)/2 = 8.5 (38+43)/2 = 40.5
every (0+0)/2 = 0 (0+0)/2 = 0 (0+0)/2 = 0
$.each (85+84)/2 = 84.5 (15+19)/2 = 17 (37+25)/2 = 31
$(e).each (81+83)/2 = 82 (34+31)/2 = 32.5 (37+46)/2 = 41.5

數(shù)組賦值后, 數(shù)組長(zhǎng)度為10^7


數(shù)組長(zhǎng)度為10^7 chrome 52.0.2743.116 (64-bit) Firefox Developer Edition 49.0a2 (2016-08-01) Safari 9.1.1 (11601.6.17)
for (171+157)/2 = 164 (27+26)/2 = 26.5 (26+28)/2 = 27
do while (168+158)/2 = 163 (27+27)/2 = 27 (28+29)/2 = 28.5
for in (1469+1715)/2 = 1592 (2922+3123)/2 = 3022.5 (5755+5742)/2 = 5748.5
forEach (347+329)/2 = 338 (32+36)/2 = 34 (171+174)/2 = 172.5
map (1320+1335)/2 = 1327.5 (147+137)/2 = 142 (448+469)/2 = 458.5
every (0+0)/2 = 0 (0+0)/2 = 0 (0+0)/2 = 0
$.each (438+441)/2 = 439.5 (142+141)/2 = 141.5 (254+248)/2 = 251
$(e).each (876+935)/2 = 905.5 (315+328)/2 = 321.5 (450+402)/2 = 426

可見, 對(duì)數(shù)組進(jìn)行賦值后, 代碼運(yùn)行基本穩(wěn)定.(every還不清楚為什么執(zhí)行時(shí)間為0.歡迎大神告知原因.)

分析總結(jié)

通過以上 30 次運(yùn)行測(cè)試(實(shí)際上為了得到比較穩(wěn)定的數(shù)據(jù), 擯棄了許多異常的測(cè)試數(shù)據(jù)), 我們發(fā)現(xiàn)在數(shù)組長(zhǎng)度為10^6, 10^7, 10^8 時(shí), 代碼運(yùn)行基本穩(wěn)定. 各方法運(yùn)行需要的時(shí)間大致排序如下:

for ~= do while < forEach ~= map ~= every < $.each < $(e).each < for in

根據(jù)統(tǒng)計(jì)數(shù)據(jù), 可得這8個(gè)方法的運(yùn)行速度大致排序?yàn)?

  1. for 與 do while
  2. forEach map every (這3個(gè)不相上下,可認(rèn)為運(yùn)行速度差不多)
  3. $.each
  4. $(e).each
  5. for in

我們翻看jquery代碼就會(huì)知道, $.each方法內(nèi)部通過調(diào)用for循環(huán)來(lái)實(shí)現(xiàn), 而$().each是先用jquery包裹數(shù)組對(duì)象, 然后再調(diào)用for循環(huán), 因此后者效率略低于前者.

綜上, 最佳遍歷選手是 for/do while循環(huán), 推薦大家優(yōu)先考慮使用它. ( Firefox瀏覽器由于對(duì)forEach循環(huán)做了底層優(yōu)化, 效率接近native,不在我們考慮范圍內(nèi) ).

基于測(cè)試結(jié)果的兩點(diǎn)思考

從測(cè)試數(shù)據(jù)上猜測(cè), Firefox 與 Safari 似乎對(duì)于 for, do while 等都進(jìn)行了底層優(yōu)化. 循環(huán)執(zhí)行效率明顯優(yōu)于Chrome.

每次瀏覽器執(zhí)行到 for in 循環(huán)處, 便會(huì)出現(xiàn)卡頓, 猜測(cè)瀏覽器可能正在預(yù)加載循環(huán)所需資源(后續(xù)我將專門分析此處).

想要進(jìn)一步優(yōu)化循環(huán)效率, 推薦您閱讀下篇 《JS作用域鏈及閉包》.

聲明: 本文所有數(shù)據(jù)均為單機(jī)測(cè)試, 難免存在誤差, 如果發(fā)現(xiàn)本文測(cè)試數(shù)據(jù)不對(duì)之處, 歡迎批評(píng)斧正.

總結(jié)

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,如果有疑問大家可以留言交流,謝謝大家對(duì)腳本之家的支持。

相關(guān)文章

  • 微信小程序路由跳轉(zhuǎn)兩種方式示例解析

    微信小程序路由跳轉(zhuǎn)兩種方式示例解析

    這篇文章主要為大家介紹了微信小程序路由跳轉(zhuǎn)兩種方式示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪
    2022-04-04
  • 詳解微信小程序圖片地扯轉(zhuǎn)base64解決方案

    詳解微信小程序圖片地扯轉(zhuǎn)base64解決方案

    這篇文章主要介紹了詳解微信小程序圖片地扯轉(zhuǎn)base64解決方案,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08
  • webpack 5 mode的作用和區(qū)別解析

    webpack 5 mode的作用和區(qū)別解析

    Webpack 5 是一款強(qiáng)大的模塊打包工具,可用于將許多分散的模塊按照依賴關(guān)系打包成一個(gè)(或多個(gè))bundle,這篇文章給大家介紹webpack 5 mode的作用和區(qū)別解析,感興趣的朋友跟隨小編一起看看吧
    2024-01-01
  • javascript 定義初始化數(shù)組函數(shù)

    javascript 定義初始化數(shù)組函數(shù)

    有段javascript代碼很困惑,經(jīng)過不斷的查資料,終于弄懂了!呵呵!
    2009-09-09
  • 詳談javascript異步編程

    詳談javascript異步編程

    這篇文章主要為大家詳細(xì)介紹了javascript異步編程,其實(shí)作為一種編程語(yǔ)言Javascript的異步編程是一個(gè)非常值得討論的有趣話題,感興趣的小伙伴們可以參考一下
    2016-02-02
  • 你可能不知道的JavaScript位運(yùn)算符詳解

    你可能不知道的JavaScript位運(yùn)算符詳解

    位運(yùn)算符是在數(shù)字底層(即表示數(shù)字的32個(gè)數(shù)位)進(jìn)行操作的,下面這篇文章主要給大家介紹了一些你可能不知道的JavaScript位運(yùn)算符的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-06-06
  • js時(shí)間戳轉(zhuǎn)yyyy-MM-dd HH-mm-ss工具類詳解

    js時(shí)間戳轉(zhuǎn)yyyy-MM-dd HH-mm-ss工具類詳解

    這篇文章主要介紹了js時(shí)間戳轉(zhuǎn)yyyy-MM-dd HH-mm-ss工具類,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • 詳解用場(chǎng)景去理解函數(shù)柯里化(入門篇)

    詳解用場(chǎng)景去理解函數(shù)柯里化(入門篇)

    這篇文章主要介紹了用場(chǎng)景去理解函數(shù)柯里化(入門篇),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • js 模擬實(shí)現(xiàn)類似c#下的hashtable的簡(jiǎn)單功能代碼

    js 模擬實(shí)現(xiàn)類似c#下的hashtable的簡(jiǎn)單功能代碼

    越來(lái)越感覺js對(duì)集合的處理沒有c#強(qiáng)大。比如在實(shí)際開發(fā)中,經(jīng)常用到在一維數(shù)組或者二維數(shù)組里取某一個(gè)滿足某些條件的項(xiàng),通常的處理方式就是遍歷數(shù)組,對(duì)比條件,匹配就取出,然后結(jié)束循環(huán)。
    2010-01-01
  • JavaScript中的幾個(gè)關(guān)鍵概念的理解-原型鏈的構(gòu)建

    JavaScript中的幾個(gè)關(guān)鍵概念的理解-原型鏈的構(gòu)建

    JavaScript中的prototype,標(biāo)準(zhǔn)翻譯為“原型”,表示對(duì)象的初始形態(tài)
    2011-05-05

最新評(píng)論