jquery.map()方法的使用詳解
原型方法map跟each類似調(diào)用的是同名靜態(tài)方法,只不過返回來的數(shù)據(jù)必須經(jīng)過另一個原型方法pushStack方法處理之后才返回,源碼如下:
map: function( callback ) { return this.pushStack( jQuery.map(this, function( elem, i ) { return callback.call( elem, i, elem ); })); },
本文主要就是分析靜態(tài)map方法至于pushStack在下一篇隨筆里面分析;
首先了解下map的使用(手冊內(nèi)容)
$.map將一個數(shù)組中的元素轉(zhuǎn)換到另一個數(shù)組中。
作為參數(shù)的轉(zhuǎn)換函數(shù)會為每個數(shù)組元素調(diào)用,而且會給這個轉(zhuǎn)換函數(shù)傳遞一個表示被轉(zhuǎn)換的元素作為參數(shù)。
轉(zhuǎn)換函數(shù)可以返回轉(zhuǎn)換后的值、null(刪除數(shù)組中的項目)或一個包含值的數(shù)組,并擴(kuò)展至原始數(shù)組中。
參數(shù)
arrayOrObject,callbackArray/Object,FunctionV1.6
arrayOrObject:數(shù)組或者對象。
為每個數(shù)組元素調(diào)用,而且會給這個轉(zhuǎn)換函數(shù)傳遞一個表示被轉(zhuǎn)換的元素作為參數(shù)。
函數(shù)可返回任何值。
另外,此函數(shù)可設(shè)置為一個字符串,當(dāng)設(shè)置為字符串時,將視為“l(fā)ambda-form”(縮寫形式?),其中 a 代表數(shù)組元素。
如“a * a”代表“function(a){ return a * a; }”。
示例1:
//將原數(shù)組中每個元素加 4 轉(zhuǎn)換為一個新數(shù)組。 //jQuery 代碼: $.map( [0,1,2], function(n){ return n + 4; }); //結(jié)果: [4, 5, 6]
示例2:
//原數(shù)組中大于 0 的元素加 1 ,否則刪除。 //jQuery 代碼: $.map( [0,1,2], function(n){ return n > 0 ? n + 1 : null; }); //結(jié)果: [2, 3]
示例3:
//原數(shù)組中每個元素擴(kuò)展為一個包含其本身和其值加 1 的數(shù)組,并轉(zhuǎn)換為一個新數(shù)組 //jQuery 代碼: $.map( [0,1,2], function(n){ return [ n, n + 1 ]; }); //結(jié)果: [0, 1, 1, 2, 2, 3]
可以看出map方法跟each方法類似通過循環(huán)每個對象或者數(shù)組的“項”執(zhí)行回調(diào)函數(shù)來實現(xiàn)對數(shù)組或者對象的操作,但是這兩個方法也有很多不同點
比如each()返回的是原來的數(shù)組,并不會新創(chuàng)建一個數(shù)組,而map則會創(chuàng)建新的數(shù)組,;each遍歷是this指向當(dāng)前數(shù)組或?qū)ο笾?,map則指向window,因為在源碼中并不像each那樣使用對象冒充;
例如:
var items = [1,2,3,4]; $.each(items, function() { alert('this is ' + this); }); var newItems = $.map(items, function(i) { return i + 1; }); // newItems is [2,3,4,5] //使用each時,改變的還是原來的items數(shù)組,而使用map時,不改變items,只是新建一個新的數(shù)組。 var items = [0,1,2,3,4,5,6,7,8,9]; var itemsLessThanEqualFive = $.map(items, function(i) { // removes all items > 5 if (i > 5) return null; return i; }); // itemsLessThanEqualFive = [0,1,2,3,4,5]
言歸正傳回到map源碼
// arg is for internal usage only map: function( elems, callback, arg ) { var value, key, ret = [], i = 0, length = elems.length, // jquery objects are treated as arrays isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ; // Go through the array, translating each of the items to their if ( isArray ) { for ( ; i < length; i++ ) { value = callback( elems[ i ], i, arg ); if ( value != null ) { ret[ ret.length ] = value; } } // Go through every key on the object, } else { for ( key in elems ) { value = callback( elems[ key ], key, arg ); if ( value != null ) { ret[ ret.length ] = value; } } } // Flatten any nested arrays return ret.concat.apply( [], ret ); },
首先還是聲明幾個變量為接下來的遍歷做準(zhǔn)備,其中jsArray變量用來簡單區(qū)分對象和數(shù)組,這個布爾復(fù)合表達(dá)式比較長不過只要記住js運算符的有優(yōu)先順序就不難理解了,首先括號優(yōu)先執(zhí)行然后就是邏輯與》邏輯或》全等》賦值,然后就可以分析啦
首先圓括號里先計算然后結(jié)果加上 length !== undefined 、 typeof length === "number這兩個必要條件最后的結(jié)果再跟elems instanceof jQuery進(jìn)行邏輯或的運算,簡單的說就是isArray為真的情況有:
1、elems instanceof jQuery 為true 換言之就是jquery對象
2、length !== undefined && typeof length === "number" 和 length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems )這三個至少成立一個
可以拆分為3個小情況
length是存在并且是數(shù)字而且待遍歷的數(shù)組或者類數(shù)組等length屬性大于0 length-1存在 這樣就保證了是能遍歷的,比如對于jquery對象 domList對象等
length是存在并且是數(shù)字而且length屬性等于0 如果是0也沒關(guān)系就是不會遍歷
length是存在并且是數(shù)字而且待遍歷對象是純數(shù)組
滿足這些條件之后開始根據(jù)isArray的結(jié)果分開遍歷,對于“數(shù)組”采用for循環(huán),對于對象采用for...in循環(huán)
// Go through the array, translating each of the items to their if ( isArray ) { for ( ; i < length; i++ ) { value = callback( elems[ i ], i, arg ); if ( value != null ) { ret[ ret.length ] = value; } }
是數(shù)組或者類數(shù)組的時候直接把循環(huán)的每一項的值和指針以及arg參數(shù)傳入回調(diào)函數(shù)中執(zhí)行,arg參數(shù)是此方法內(nèi)部使用的參數(shù),跟each以及一些其他jquery方法很相似,只要在執(zhí)行回調(diào)函數(shù)時不返回null就把執(zhí)行返回的結(jié)果添加到新數(shù)組中,對象操作亦是如此直接略過
// Flatten any nested arrays return ret.concat.apply( [], ret );
最后將結(jié)果集扁平化,為什么有這一步呢?因為map是可以擴(kuò)展數(shù)組的在前面第3個示例就是如此:
$.map( [0,1,2], function(n){ return [ n, n + 1 ]; });
如果是這樣使用的話得到的新數(shù)組是一個二維數(shù)組,所以必須降維
ret.concat.apply( [], ret )等價于[].concat.apply([],ret)關(guān)鍵作用的是apply,因為apply的第二個參數(shù)把ret的數(shù)組分成多個參數(shù)傳入給concat把二維數(shù)組轉(zhuǎn)化為一維數(shù)組這個用法還是值得收藏的的
map方法簡單分析完畢,能力有限錯誤之處望多多指正。
以上所述就是本文的全部內(nèi)容了,希望大家能夠喜歡。
相關(guān)文章
那些年,我還在學(xué)習(xí)jquery 學(xué)習(xí)筆記
那些年學(xué)習(xí)了一些基本的web開發(fā)知識,其中已經(jīng)有javascript語言了,為什么還要學(xué)習(xí)Jquery啊2012-03-03jquery實現(xiàn)側(cè)邊欄左右伸縮效果的示例
下面小編就為大家分享一篇jquery實現(xiàn)側(cè)邊欄左右伸縮效果的示例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2017-12-12jQuery動態(tài)設(shè)置form表單的enctype值(實現(xiàn)代碼)
本篇文章是對在jQuery中動態(tài)設(shè)置form表單的enctype值的實現(xiàn)代碼進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-07-07jquery+json實現(xiàn)數(shù)據(jù)二級聯(lián)動的方法
這篇文章主要介紹了jquery+json實現(xiàn)數(shù)據(jù)二級聯(lián)動的方法,涉及jQuery基于get方法與后臺.net程序傳輸json交互實現(xiàn)二級聯(lián)動菜單,具有一定參考借鑒價值,需要的朋友可以參考下2015-11-11select標(biāo)簽?zāi)M/美化方法采用JS外掛式插件
select標(biāo)簽的外觀問題很惱人,各個瀏覽器都不一致,單單就IE,一個版本就一個長相,還不能用CSS修飾,接下來將本人對select的美化方法共享出來,感興趣的朋友可以參考下2013-04-04jquery判斷復(fù)選框選中狀態(tài)以及區(qū)分attr和prop
這篇文章主要介紹了jquery判斷復(fù)選框選中狀態(tài)以及區(qū)分attr和prop,感興趣的小伙伴們可以參考一下2015-12-12