本文給大家詳細介紹了jQuery中的原型方法map的使用指南和源碼分析,十分的不錯,對于大家學習jQuery非常有幫助,這里推薦給大家。
原型方法map跟each類似調用的是同名靜態方法,只不過返回來的數據必須經過另一個原型方法pushStack方法處理之后才返回,源碼如下:
- map: function( callback ) {
- return this.pushStack( jQuery.map(this, function( elem, i ) {
- return callback.call( elem, i, elem );
- }));
- },
本文主要就是分析靜態map方法至于pushStack在下一篇隨筆里面分析;
首先了解下map的使用(手冊內容)
$.map將一個數組中的元素轉換到另一個數組中。
作為參數的轉換函數會為每個數組元素調用,而且會給這個轉換函數傳遞一個表示被轉換的元素作為參數。
轉換函數可以返回轉換后的值、null(刪除數組中的項目)或一個包含值的數組,并擴展至原始數組中。
參數
arrayOrObject,callbackArray/Object,FunctionV1.6
arrayOrObject:數組或者對象。
為每個數組元素調用,而且會給這個轉換函數傳遞一個表示被轉換的元素作為參數。
函數可返回任何值。
另外,此函數可設置為一個字符串,當設置為字符串時,將視為“lambda-form”(縮寫形式?),其中 a 代表數組元素。
如“a * a”代表“function(a){ return a * a; }”。
示例1:
- //將原數組中每個元素加 4 轉換為一個新數組。
- //jQuery 代碼:
- $.map( [0,1,2], function(n){
- return n + 4;
- });
- //結果:
- [4, 5, 6]
示例2:
- //原數組中大于 0 的元素加 1 ,否則刪除。
- //jQuery 代碼:
- $.map( [0,1,2], function(n){
- return n > 0 ? n + 1 : null;
- });
- //結果:
- [2, 3]
示例3:
- //原數組中每個元素擴展為一個包含其本身和其值加 1 的數組,并轉換為一個新數組
- //jQuery 代碼:
- $.map( [0,1,2], function(n){
- return [ n, n + 1 ];
- });
- //結果:
- [0, 1, 1, 2, 2, 3]
可以看出map方法跟each方法類似通過循環每個對象或者數組的“項”執行回調函數來實現對數組或者對象的操作,但是這兩個方法也有很多不同點
比如each()返回的是原來的數組,并不會新創建一個數組,而map則會創建新的數組,;each遍歷是this指向當前數組或對象值,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數組,而使用map時,不改變items,只是新建一個新的數組。
- 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 );
- },
首先還是聲明幾個變量為接下來的遍歷做準備,其中jsArray變量用來簡單區分對象和數組,這個布爾復合表達式比較長不過只要記住js運算符的有優先順序就不難理解了,首先括號優先執行然后就是邏輯與》邏輯或》全等》賦值,然后就可以分析啦
首先圓括號里先計算然后結果加上 length !== undefined 、 typeof length === "number這兩個必要條件最后的結果再跟elems instanceof jQuery進行邏輯或的運算,簡單的說就是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是存在并且是數字而且待遍歷的數組或者類數組等length屬性大于0 length-1存在 這樣就保證了是能遍歷的,比如對于jquery對象 domList對象等
length是存在并且是數字而且length屬性等于0 如果是0也沒關系就是不會遍歷
length是存在并且是數字而且待遍歷對象是純數組
滿足這些條件之后開始根據isArray的結果分開遍歷,對于“數組”采用for循環,對于對象采用for...in循環
- // 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;
- }
- }
是數組或者類數組的時候直接把循環的每一項的值和指針以及arg參數傳入回調函數中執行,arg參數是此方法內部使用的參數,跟each以及一些其他jquery方法很相似,只要在執行回調函數時不返回null就把執行返回的結果添加到新數組中,對象操作亦是如此直接略過
- // Flatten any nested arrays
- return ret.concat.apply( [], ret );
最后將結果集扁平化,為什么有這一步呢?因為map是可以擴展數組的在前面第3個示例就是如此:
- $.map( [0,1,2], function(n){
- return [ n, n + 1 ];
- });
如果是這樣使用的話得到的新數組是一個二維數組,所以必須降維
ret.concat.apply( [], ret )等價于[].concat.apply([],ret)關鍵作用的是apply,因為apply的第二個參數把ret的數組分成多個參數傳入給concat把二維數組轉化為一維數組這個用法還是值得收藏的的
map方法簡單分析完畢,能力有限錯誤之處望多多指正。
以上所述就是本文的全部內容了,希望大家能夠喜歡。
新聞熱點
疑難解答
圖片精選