亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

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

blankyao / 2072人閱讀

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

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

each介紹

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

語法為:

jQuery.each(object, [callback])

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

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

// Item #0: 0
// Item #1: 1
// Item #2: 2
// 遍歷對象
$.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),除了拋出一個異常。但是對于 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
第一版

那么我們該怎么實現(xiàn)這樣一個 each 方法呢?

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

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

那么又該如何判斷類數(shù)組對象和數(shù)組呢?實際上,我們在《JavaScript專題之類型判斷(下)》就講過jQuery 數(shù)組和類數(shù)組對象判斷函數(shù) isArrayLike 的實現(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)可以遍歷對象和數(shù)組了,但是依然有一個效果沒有實現(xiàn),就是中止循環(huán),按照 jQuery each 的實現(xiàn),當回調(diào)函數(shù)返回 false 的時候,我們就中止循環(huán)。這個實現(xiàn)起來也很簡單:

我們只用把:

callback(i, obj[i])

替換成:

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

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

this

我們在實際的開發(fā)中,我們有時會在 callback 函數(shù)中用到 this,先舉個不怎么恰當?shù)睦樱?/p>

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

console.log(person)

這個時候,我們就希望 this 能指向當前遍歷的元素,然后給每個元素添加 age 屬性。

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

我們把:

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

替換成:

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

關于 this,我們再舉個常用的例子:

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

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

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

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

回到第一種寫法上,就是因為將 this 指向了當前 DOM 元素,我們才能使用 $(this)將當前 DOM 元素包裝成 jQuery 對象,優(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;
}
性能比較

我們在性能上比較下 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")

這里顯示一次運算的結果:

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

我們再看一個例子:

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")

這里顯示一次運算的結果:

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

有舍有得吧。

專題系列

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

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

如果有錯誤或者不嚴謹?shù)牡胤?,請務必給予指正,十分感謝。如果喜歡或者有所啟發(fā),歡迎 star,對作者也是一種鼓勵。

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

轉載請注明本文地址:http://www.ezyhdfw.cn/yun/84603.html

相關文章

  • JavaScript專題系列文章

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

    Maxiye 評論0 收藏0
  • JavaScript專題系列20篇正式完結!

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

    sixleaves 評論0 收藏0
  • underscore 系列如何寫自己 underscore

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

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

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

    zhangfaliang 評論0 收藏0
  • 2017-08-03 前端日報

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

    gecko23 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<