map()是underscore.js中一個處理數組和對象的方法。 params: 1. array || obj 2. callback 3. content 上下文指向 使用: 這個代碼如果我自己寫的話當然很簡單的想法了,就是判斷傳入參數類型,進行遍歷,然後判斷是否有回調,有的話,就執行,並將結 ...
map()是underscore.js中一個處理數組和對象的方法。
params:
1. array || obj
2. callback
3. content 上下文指向
使用:
var obj = {a:1, b: 2, c: 3}
var arr = [1.3,5,6,76]
_.map(arr, function(value, index, obj){
return value*3
});
這個代碼如果我自己寫的話當然很簡單的想法了,就是判斷傳入參數類型,進行遍歷,然後判斷是否有回調,有的話,就執行,並將結果返回出去,沒有的話,就將原值返回出去。
下麵看下源碼是怎樣的吧。
調用過程:
map():
_.map = function (obj, iteratee, context) { iteratee = cb(iteratee, context); var keys = !isArray(obj) && Object.keys(obj); var length = (keys || obj).length; var result = Array(length); for(var index = 0; index < length; index++) { var current = keys ? keys[index] : index; result[index] = iteartee(obj[current], index, obj); } } map方法在一開始調用了一個cb方法,對iteratee進行重寫,下麵看下cb
cb()
var defaultCb = function(value) { return value; } /** * argcount 在生成迭代的時候,對迭代器有幾個參數的要求,預設3 * */ var cb = function(value, context, argcount) { if (value == null ) return defaultCb; if (isFunc(value)) return optimizeCb(value, context, argCount); ... } 這裡其實沒什麼好說的,如果沒有回調,就給他一個預設方法。重點應該是在optimizeCb方法上。
optimizeCb()
var optimizeCb = function(func, context, argCount) { if (context == void 0 ) return func; switch (argCount == null ? 3 : argCount) { case 1: return function(value) { return func.call(context, value) } ... case 3: return function(value, index, object) { return func.call(context, value, index, object); } } } 在optimizeCb中,會註意到underscore使用了void 0 來代替undefined進行判斷。 void是js的一個函數,但是,似乎很少用到,由於void的返回值是undefined,於是,被代替undefined以用來判斷,畢竟,相比undefined,可以改寫這一點,void更可靠一點 可以看到,在optimizeCb中使用了call函數,對func重新綁定了上下文,並返回。
其實在map方法中,主要的是iteratee設計(迭代設計),迭代可以基本大家都知道,但是卻不十分瞭解。
迭代: 簡單的說:就是通過某一種方法對數組,對象以及類數組中的每個元素進行處理。
而一個迭代器,至少有兩個基礎部分:
- 被迭代集合
- 當前迭代過程
而map中的迭代過程則是一個函數,就是傳入的處理函數。至於cb函數,則是根據傳參的不同情況創建迭代過程,為每次的迭代服務。
optimizeCb函數是對迭代函數的一個優化,基本上,map方法是通過迭代,對數據進行操作,從而返回一個新數組