成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

JavaScript專題之jQuery通用遍歷方法each的實(shí)現(xiàn)

blankyao / 1996人閱讀

摘要:語法為回調(diào)函數(shù)擁有兩個(gè)參數(shù)第一個(gè)為對(duì)象的成員或數(shù)組的索引,第二個(gè)為對(duì)應(yīng)變量或內(nèi)容。但是對(duì)于的函數(shù),如果需要退出循環(huán)可使回調(diào)函數(shù)返回,其它返回值將被忽略。

JavaScript 專題系列第十一篇,講解 jQuery 通用遍歷方法 each 的實(shí)現(xiàn)

each介紹

jQuery 的 each 方法,作為一個(gè)通用遍歷方法,可用于遍歷對(duì)象和數(shù)組。

語法為:

jQuery.each(object, [callback])

回調(diào)函數(shù)擁有兩個(gè)參數(shù):第一個(gè)為對(duì)象的成員或數(shù)組的索引,第二個(gè)為對(duì)應(yīng)變量或內(nèi)容。

// 遍歷數(shù)組
$.each( [0,1,2], function(i, n){
    console.log( "Item #" + i + ": " + n );
});

// Item #0: 0
// Item #1: 1
// Item #2: 2
// 遍歷對(duì)象
$.each({ name: "John", lang: "JS" }, function(i, n) {
    console.log("Name: " + i + ", Value: " + n);
});
// Name: name, Value: John
// Name: lang, Value: JS
退出循環(huán)

盡管 ES5 提供了 forEach 方法,但是 forEach 沒有辦法中止或者跳出 forEach 循環(huán),除了拋出一個(gè)異常。但是對(duì)于 jQuery 的 each 函數(shù),如果需要退出 each 循環(huán)可使回調(diào)函數(shù)返回 false,其它返回值將被忽略。

$.each( [0, 1, 2, 3, 4, 5], function(i, n){
    if (i > 2) return false;
    console.log( "Item #" + i + ": " + n );
});

// Item #0: 0
// Item #1: 1
// Item #2: 2
第一版

那么我們?cè)撛趺磳?shí)現(xiàn)這樣一個(gè) each 方法呢?

首先,我們肯定要根據(jù)參數(shù)的類型進(jìn)行判斷,如果是數(shù)組,就調(diào)用 for 循環(huán),如果是對(duì)象,就使用 for in 循環(huán),有一個(gè)例外是類數(shù)組對(duì)象,對(duì)于類數(shù)組對(duì)象,我們依然可以使用 for 循環(huán)。

更多關(guān)于類數(shù)組對(duì)象的知識(shí),我們可以查看《JavaScript專題之類數(shù)組對(duì)象與arguments》

那么又該如何判斷類數(shù)組對(duì)象和數(shù)組呢?實(shí)際上,我們?cè)凇禞avaScript專題之類型判斷(下)》就講過jQuery 數(shù)組和類數(shù)組對(duì)象判斷函數(shù) isArrayLike 的實(shí)現(xiàn)。

所以,我們可以輕松寫出第一版:

// 第一版
function each(obj, callback) {
    var length, i = 0;

    if ( isArrayLike(obj) ) {
        length = obj.length;
        for ( ; i < length; i++ ) {
            callback(i, obj[i])
        }
    } else {
        for ( i in obj ) {
            callback(i, obj[i])
        }
    }

    return obj;
}
中止循環(huán)

現(xiàn)在已經(jīng)可以遍歷對(duì)象和數(shù)組了,但是依然有一個(gè)效果沒有實(shí)現(xiàn),就是中止循環(huán),按照 jQuery each 的實(shí)現(xiàn),當(dāng)回調(diào)函數(shù)返回 false 的時(shí)候,我們就中止循環(huán)。這個(gè)實(shí)現(xiàn)起來也很簡單:

我們只用把:

callback(i, obj[i])

替換成:

if (callback(i, obj[i]) === false) {
    break;
}

輕松實(shí)現(xiàn)中止循環(huán)的功能。

this

我們?cè)趯?shí)際的開發(fā)中,我們有時(shí)會(huì)在 callback 函數(shù)中用到 this,先舉個(gè)不怎么恰當(dāng)?shù)睦樱?/p>

// 我們給每個(gè)人添加一個(gè) age 屬性,age 的值為 18 + index
var person = [
    {name: "kevin"},
    {name: "daisy"}
]
$.each(person, function(index, item){
    this.age = 18 + index;
})

console.log(person)

這個(gè)時(shí)候,我們就希望 this 能指向當(dāng)前遍歷的元素,然后給每個(gè)元素添加 age 屬性。

指定 this,我們可以使用 call 或者 apply,其實(shí)也很簡單:

我們把:

if (callback(i, obj[i]) === false) {
    break;
}

替換成:

if (callback.call(obj[i], i, obj[i]) === false) {
    break;
}

關(guān)于 this,我們?cè)倥e個(gè)常用的例子:

$.each($("p"), function(){
   $(this).hover(function(){ ... });
})

雖然我們經(jīng)常會(huì)這樣寫:

$("p").each(function(){
    $(this).hover(function(){ ... });
})

但是因?yàn)?$("p").each() 方法是定義在 jQuery 函數(shù)的 prototype 對(duì)象上面的,而 $.data()方法是定義 jQuery 函數(shù)上面的,調(diào)用的時(shí)候不從復(fù)雜的 jQuery 對(duì)象上調(diào)用,速度快得多。所以我們推薦使用第一種寫法。

回到第一種寫法上,就是因?yàn)閷?this 指向了當(dāng)前 DOM 元素,我們才能使用 $(this)將當(dāng)前 DOM 元素包裝成 jQuery 對(duì)象,優(yōu)雅的使用 hover 方法。

所以最終的 each 源碼為:

function each(obj, callback) {
    var length, i = 0;

    if (isArrayLike(obj)) {
        length = obj.length;
        for (; i < length; i++) {
            if (callback.call(obj[i], i, obj[i]) === false) {
                break;
            }
        }
    } else {
        for (i in obj) {
            if (callback.call(obj[i], i, obj[i]) === false) {
                break;
            }
        }
    }

    return obj;
}
性能比較

我們?cè)谛阅苌媳容^下 for 循環(huán)和 each 函數(shù):

var arr = Array.from({length: 1000000}, (v, i) => i);

console.time("for")
var i = 0;
for (; i < arr.length; i++) {
    i += arr[i];
}
console.timeEnd("for")


console.time("each")
var j = 0;
$.each(arr, function(index, item){
    j += item;
})
console.timeEnd("each")

這里顯示一次運(yùn)算的結(jié)果:

從上圖可以看出,for 循環(huán)的性能是明顯好于 each 函數(shù)的,each 函數(shù)本質(zhì)上也是用的 for 循環(huán),到底是慢在了哪里呢?

我們?cè)倏匆粋€(gè)例子:

function each(obj, callback) {
    var i = 0;
    var length = obj.length
    for (; i < length; i++) {
        value = callback(i, obj[i]);
    }
}

function eachWithCall(obj, callback) {
    var i = 0;
    var length = obj.length
    for (; i < length; i++) {
        value = callback.call(obj[i], i, obj[i]);
    }
}

var arr = Array.from({length: 1000000}, (v, i) => i);

console.time("each")
var i = 0;
each(arr, function(index, item){
    i += item;
})
console.timeEnd("each")


console.time("eachWithCall")
var j = 0;
eachWithCall(arr, function(index, item){
    j += item;
})
console.timeEnd("eachWithCall")

這里顯示一次運(yùn)算的結(jié)果:

each 函數(shù)和 eachWithCall 函數(shù)唯一的區(qū)別就是 eachWithCall 調(diào)用了 call,從結(jié)果我們可以推測(cè)出,call 會(huì)導(dǎo)致性能損失,但也正是 call 的存在,我們才能將 this 指向循環(huán)中當(dāng)前的元素。

有舍有得吧。

專題系列

JavaScript專題系列目錄地址:https://github.com/mqyqingfeng/Blog。

JavaScript專題系列預(yù)計(jì)寫二十篇左右,主要研究日常開發(fā)中一些功能點(diǎn)的實(shí)現(xiàn),比如防抖、節(jié)流、去重、類型判斷、拷貝、最值、扁平、柯里、遞歸、亂序、排序等,特點(diǎn)是研(chao)究(xi) underscore 和 jQuery 的實(shí)現(xiàn)方式。

如果有錯(cuò)誤或者不嚴(yán)謹(jǐn)?shù)牡胤?,?qǐng)務(wù)必給予指正,十分感謝。如果喜歡或者有所啟發(fā),歡迎 star,對(duì)作者也是一種鼓勵(lì)。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/84603.html

相關(guān)文章

  • JavaScript專題系列文章

    摘要:專題系列共計(jì)篇,主要研究日常開發(fā)中一些功能點(diǎn)的實(shí)現(xiàn),比如防抖節(jié)流去重類型判斷拷貝最值扁平柯里遞歸亂序排序等,特點(diǎn)是研究專題之函數(shù)組合專題系列第十六篇,講解函數(shù)組合,并且使用柯里化和函數(shù)組合實(shí)現(xiàn)模式需求我們需要寫一個(gè)函數(shù),輸入,返回。 JavaScript 專題之從零實(shí)現(xiàn) jQuery 的 extend JavaScritp 專題系列第七篇,講解如何從零實(shí)現(xiàn)一個(gè) jQuery 的 ext...

    Maxiye 評(píng)論0 收藏0
  • JavaScript專題系列20篇正式完結(jié)!

    摘要:寫在前面專題系列是我寫的第二個(gè)系列,第一個(gè)系列是深入系列。專題系列自月日發(fā)布第一篇文章,到月日發(fā)布最后一篇,感謝各位朋友的收藏點(diǎn)贊,鼓勵(lì)指正。 寫在前面 JavaScript 專題系列是我寫的第二個(gè)系列,第一個(gè)系列是 JavaScript 深入系列。 JavaScript 專題系列共計(jì) 20 篇,主要研究日常開發(fā)中一些功能點(diǎn)的實(shí)現(xiàn),比如防抖、節(jié)流、去重、類型判斷、拷貝、最值、扁平、柯里...

    sixleaves 評(píng)論0 收藏0
  • underscore 系列如何寫自己 underscore

    摘要:因?yàn)樵谖⑿判〕绦蛑?,和都是,加上又?qiáng)制使用嚴(yán)格模式,為,掛載就會(huì)發(fā)生錯(cuò)誤,所以就有人又發(fā)了一個(gè),代碼變成了這就是現(xiàn)在的樣子。 前言 在 《JavaScript 專題系列》 中,我們寫了很多的功能函數(shù),比如防抖、節(jié)流、去重、類型判斷、扁平數(shù)組、深淺拷貝、查找數(shù)組元素、通用遍歷、柯里化、函數(shù)組合、函數(shù)記憶、亂序等,可以我們?cè)撊绾谓M織這些函數(shù),形成自己的一個(gè)工具函數(shù)庫呢?這個(gè)時(shí)候,我們就要借...

    Invoker 評(píng)論0 收藏0
  • JavaScript專題函數(shù)柯里化

    摘要:一個(gè)經(jīng)常會(huì)看到的函數(shù)的實(shí)現(xiàn)為第一版我們可以這樣使用或者或者已經(jīng)有柯里化的感覺了,但是還沒有達(dá)到要求,不過我們可以把這個(gè)函數(shù)用作輔助函數(shù),幫助我們寫真正的函數(shù)。 JavaScript 專題系列第十三篇,講解函數(shù)柯里化以及如何實(shí)現(xiàn)一個(gè) curry 函數(shù) 定義 維基百科中對(duì)柯里化 (Currying) 的定義為: In mathematics and computer science, cu...

    zhangfaliang 評(píng)論0 收藏0
  • 2017-08-03 前端日?qǐng)?bào)

    摘要:前端日?qǐng)?bào)精選專題之通用遍歷方法的實(shí)現(xiàn)深入了解的子組件上最流行的項(xiàng)目再聊移動(dòng)端頁面的適配譯盒子模型實(shí)踐教程中文全棧第天數(shù)據(jù)驅(qū)動(dòng)龍?jiān)迫珬Wg年開發(fā)趨勢(shì)瘋狂的技術(shù)宅在翻譯譯閉包并不神秘前端心得拼多多前端筆試個(gè)人文章容器技術(shù)方 2017-08-03 前端日?qǐng)?bào) 精選 JavaScript專題之jQuery通用遍歷方法each的實(shí)現(xiàn)深入了解React的子組件GitHub上最流行的Top 10 Jav...

    gecko23 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<