Underscore 是一個 JavaScript 函式庫,提供許多有用的函式程式設計輔助程式,而不會延伸任何內建物件。它是回答「如果我坐在一個空白的 HTML 頁面前,並希望立即開始生產,我需要什麼?」這個問題的答案…以及與 jQuery 的燕尾服和 Backbone 的吊帶搭配的領帶。

Underscore 提供超過 100 個函式,支援您最喜愛的日常函式輔助程式:mapfilterinvoke,以及更專業的優點:函式繫結、javascript 範本、建立快速索引、深度相等性測試等。

包含一個完整的 測試套件 供您參閱。

您也可以閱讀 帶註解的原始碼。還有一個 模組化版本,其中包含可點擊的匯入參考。

您可以在單體和模組化匯入之間進行選擇。以下是有關選項的快速摘要,以及 文章 中更全面的討論。

享受 Underscore,並希望將它調到 11?試試 Underscore-contrib

此專案 託管在 GitHub 上。您可以在 問題頁面 上回報錯誤並討論功能,或在 Gitter 頻道中聊天。

您可以透過在 Patreon 上捐款來支持此專案。企業涵蓋範圍可用作 Tidelift 訂閱 的一部分。

Underscore 是 DocumentCloud 的開源元件。

v1.13.6 下載 (右鍵按一下,然後使用「另存新檔」)

65.9 KB,未壓縮且有豐富的註解  (原始碼對應表)
8.59 KB,已縮小且 Gzipped  (原始碼對應表)
68.4 KB,未壓縮且有豐富註解  (原始碼對應表)
7.48 KB,已縮小且 Gzipped  (原始碼對應表)
未發布,目前的 master,請自行判斷並自行承擔風險使用
未發布,目前的 master,如果您覺得幸運,請使用

v1.13.6 CDN URL (與 <script src="..."></script> 搭配使用)

在大部分情況下,您可以將上述版本號碼替換為 latest,讓您的嵌入自動使用最新版本,或者 stable,如果您想延後更新,直到更新已證明沒有意外的重大變更。範例
https://cdn.jsdelivr.net/npm/underscore@latest/underscore-umd-min.js

套件安裝

如果您在套件中硬編碼檔案路徑,而且不確定要使用哪個建置,那麼您很可能需要 underscore-umd.js 或縮小的變體 underscore-umd-min.js

整體匯入(建議)

模組化匯入

對於具有多個別名的函式,模組的檔案名稱永遠是文件中的第一個名稱。例如,_.reduce/_.inject/_.foldlunderscore/modules/reduce.js 匯出。模組化使用最適合用於建立 Underscore 的自訂建置。

引擎相容性

Underscore 1.x 向後相容於完全支援 ES3 的任何引擎,同時也會在可用的時候使用較新的功能,例如 Object.keys、已輸入陣列和 ES 模組。我們會定期對下列 JavaScript 引擎執行單元測試

此外

Underscore 2.x 可能會移除對某些過時環境的支援。

集合函式 (陣列或物件)

each_.each(list, iteratee, [context]) 別名:forEach 來源
遍歷一個元素的清單,依序傳遞給迭代器函數。如果傳遞的話,迭代器會繫結到內容物件。每次呼叫迭代器時,都會傳遞三個參數:(元素、索引、清單)。如果清單是 JavaScript 物件,迭代器的參數會是 (值、金鑰、清單)。傳回清單以串連。

_.each([1, 2, 3], alert);
=> alerts each number in turn...
_.each({one: 1, two: 2, three: 3}, alert);
=> alerts each number value in turn...

注意:集合函數適用於陣列、物件和類似陣列的物件,例如 argumentsNodeList 等。但它會透過鴨子辨識法運作,所以請避免傳遞具有數字 length 屬性的物件。另外請注意,無法中斷 each 迴圈 — 如果要中斷,請改用 _.find

map_.map(list, iteratee, [context]) 別名:collect 原始碼
透過轉換函數 (iteratee) 對清單中的每個值進行對應,產生一個新的值陣列。iteratee 會傳遞三個參數:索引(或金鑰)和整個清單的參考。

_.map([1, 2, 3], function(num){ return num * 3; });
=> [3, 6, 9]
_.map({one: 1, two: 2, three: 3}, function(num, key){ return num * 3; });
=> [3, 6, 9]
_.map([[1, 2], [3, 4]], _.first);
=> [1, 3]

reduce_.reduce(list, iteratee, [memo], [context]) 別名:injectfoldl 原始碼
又稱為 injectfoldl,reduce 將 list 中的值簡化成單一值。Memo 是簡化的初始狀態,而每個後續步驟都應由 iteratee 傳回。iteratee 會傳入四個參數:memovalue 和反覆運算的 index(或鍵),最後是整個 list 的參考。

如果在 reduce 的初始呼叫中未傳入 memo,則 iteratee 就不會在 list 的第一個元素上呼叫。第一個元素會在 iteratee 下一次呼叫 list 中的下一個元素時傳入為 memo。

var sum = _.reduce([1, 2, 3], function(memo, num){ return memo + num; }, 0);
=> 6

reduceRight_.reduceRight(list, iteratee, [memo], [context]) 別名:foldr 原始碼
reduce 的右結合版本。Foldr 在 JavaScript 中不如在有延遲評估的語言中那麼有用。

var list = [[0, 1], [2, 3], [4, 5]];
var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []);
=> [4, 5, 2, 3, 0, 1]

find_.find(list, predicate, [context]) 別名:detect 原始碼
查看 list 中的每個值,傳回第一個通過真值測試(predicate)的值,或 undefined(如果沒有值通過測試)。此函數會在找到可接受的元素後立即傳回,而不會遍歷整個 list。predicate 會透過 iteratee 轉換,以利簡寫語法。

var even = _.find([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
=> 2

filter_.filter(list, predicate, [context]) 別名:select 原始碼
檢視 list 中的每個值,傳回通過真值測試 (predicate) 的所有值的陣列。predicate 會透過 iteratee 轉換,以利簡寫語法。

var evens = _.filter([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
=> [2, 4, 6]

findWhere_.findWhere(list, properties) 原始碼
檢視 list 並傳回與 properties 中列出的所有鍵值配對 相符第一個值。

如果找不到相符項,或如果 list 為空,將傳回未定義

_.findWhere(publicServicePulitzers, {newsroom: "The New York Times"});
=> {year: 1918, newsroom: "The New York Times",
  reason: "For its public service in publishing in full so many official reports,
  documents and speeches by European statesmen relating to the progress and
  conduct of the war."}

where_.where(list, properties) 原始碼
檢視 list 中的每個值,傳回與 properties 中列出的鍵值配對 相符 的所有值的陣列。

_.where(listOfPlays, {author: "Shakespeare", year: 1611});
=> [{title: "Cymbeline", author: "Shakespeare", year: 1611},
    {title: "The Tempest", author: "Shakespeare", year: 1611}]

reject_.reject(list, predicate, [context]) 原始碼
傳回 list 中沒有通過真值測試 (predicate) 的元素的值。filter 的相反。predicate 會透過 iteratee 轉換,以利簡寫語法。

var odds = _.reject([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
=> [1, 3, 5]

every_.every(list, [predicate], [context]) 別名:all 原始碼
如果 list 中的所有值都通過 predicate 真值測試,則傳回true。如果找到 false 元素,則會短路並停止遍歷清單。predicate 會透過 iteratee 轉換,以利簡寫語法。

_.every([2, 4, 5], function(num) { return num % 2 == 0; });
=> false

some_.some(list, [predicate], [context]) 別名:any 原始碼
如果 list 中的任何值通過 predicate 真實性測試,則傳回 true。如果找到真實元素,則短路並停止遍歷列表。predicate 通過 iteratee 轉換,以簡化速記語法。

_.some([null, 0, 'yes', false]);
=> true

contains_.contains(list, value, [fromIndex]) 別名:includeincludes 來源
如果 list 中存在 value,則傳回 true。如果 list 是陣列,則在內部使用 indexOf。使用 fromIndex 從給定索引開始搜尋。

_.contains([1, 2, 3], 3);
=> true

invoke_.invoke(list, methodName, *arguments) 來源
list 中的每個值呼叫 methodName 指定的方法。傳遞給 invoke 的任何額外參數都將轉發到方法呼叫。

_.invoke([[5, 1, 7], [3, 2, 1]], 'sort');
=> [[1, 5, 7], [1, 2, 3]]

pluck_.pluck(list, propertyName) 來源
map 最常見用例的便利版本:擷取屬性值清單。

var stooges = [{name: 'moe', age: 40}, {name: 'larry', age: 50}, {name: 'curly', age: 60}];
_.pluck(stooges, 'name');
=> ["moe", "larry", "curly"]

max_.max(list, [iteratee], [context]) 來源
傳回 list 中的最大值。如果提供 iteratee 函數,則會在每個值上使用該函數來產生對應值的排名標準。如果 list 為空,則傳回 -Infinity,因此可能需要 isEmpty 守衛。目前,此函數只能可靠地比較數字。此函數使用運算子 <註解)。

var stooges = [{name: 'moe', age: 40}, {name: 'larry', age: 50}, {name: 'curly', age: 60}];
_.max(stooges, function(stooge){ return stooge.age; });
=> {name: 'curly', age: 60};

min_.min(list, [iteratee], [context]) 來源
傳回 list 中的最小值。如果提供 iteratee 函式,則會用於每個值,以產生用於對值進行排名的準則。如果 list 為空,則會傳回 Infinity,因此可能需要 isEmpty 保護。目前,此函式只能可靠地比較數字。此函式使用運算子 < (註解).

var numbers = [10, 5, 100, 2, 1000];
_.min(numbers);
=> 2

sortBy_.sortBy(list, iteratee, [context]) 來源
傳回 list 的(穩定)排序副本,依據透過 iteratee 執行每個值的結果,以遞增順序排序。iteratee 也可能是要排序的屬性的字串名稱(例如 length)。此函式使用運算子 < (註解).

_.sortBy([1, 2, 3, 4, 5, 6], function(num){ return Math.sin(num); });
=> [5, 4, 6, 3, 1, 2]

var stooges = [{name: 'moe', age: 40}, {name: 'larry', age: 50}, {name: 'curly', age: 60}];
_.sortBy(stooges, 'name');
=> [{name: 'curly', age: 60}, {name: 'larry', age: 50}, {name: 'moe', age: 40}];

groupBy_.groupBy(list, iteratee, [context]) 來源
將集合分割成多個集合,依據透過 iteratee 執行每個值的結果進行分組。如果 iteratee 是字串而非函式,則依據每個值中 iteratee 所指定的屬性進行分組。

_.groupBy([1.3, 2.1, 2.4], function(num){ return Math.floor(num); });
=> {1: [1.3], 2: [2.1, 2.4]}

_.groupBy(['one', 'two', 'three'], 'length');
=> {3: ["one", "two"], 5: ["three"]}

indexBy_.indexBy(list, iteratee, [context]) 來源
給定一個list,和一個iteratee函數,為list中每個元素傳回一個鍵值(或屬性名稱),傳回一個包含每個項目索引的物件。就像groupBy,但用於已知鍵值是唯一時。

var stooges = [{name: 'moe', age: 40}, {name: 'larry', age: 50}, {name: 'curly', age: 60}];
_.indexBy(stooges, 'age');
=> {
  "40": {name: 'moe', age: 40},
  "50": {name: 'larry', age: 50},
  "60": {name: 'curly', age: 60}
}

countBy_.countBy(list, iteratee, [context]) 來源
將清單分類成群組,並傳回每個群組中物件的數量。類似於groupBy,但傳回的不是值清單,而是該群組中值數量的計數。

_.countBy([1, 2, 3, 4, 5], function(num) {
  return num % 2 == 0 ? 'even': 'odd';
});
=> {odd: 3, even: 2}

shuffle_.shuffle(list) 來源
使用Fisher-Yates 洗牌演算法,傳回list的洗牌副本。

_.shuffle([1, 2, 3, 4, 5, 6]);
=> [4, 1, 6, 3, 5, 2]

sample_.sample(list, [n]) 來源
list中產生一個隨機樣本。傳遞一個數字以從清單中傳回n個隨機元素。否則,將傳回單一隨機項目。

_.sample([1, 2, 3, 4, 5, 6]);
=> 4

_.sample([1, 2, 3, 4, 5, 6], 3);
=> [1, 6, 2]

toArray_.toArray(list) 來源
list(任何可迭代的項目)建立一個真正的陣列。對於轉換arguments物件很有用。

(function(){ return _.toArray(arguments).slice(1); })(1, 2, 3, 4);
=> [2, 3, 4]

size_.size(list) 來源
傳回list中的值數量。

_.size([1, 2, 3, 4, 5]);
=> 5

_.size({one: 1, two: 2, three: 3});
=> 3

partition_.partition(list, predicate) 來源
清單分割成兩個陣列:一個元素全部滿足謂詞,另一個元素全部不滿足謂詞謂詞透過 迭代器 轉換,以利簡寫語法。

_.partition([0, 1, 2, 3, 4, 5], isOdd);
=> [[1, 3, 5], [0, 2, 4]]

compact_.compact(list) 來源
傳回清單的複本,移除所有假值。在 JavaScript 中,falsenull0""undefinedNaN 都是假值。

_.compact([0, 1, false, 2, '', 3]);
=> [1, 2, 3]

陣列函式

注意:所有陣列函式也會在引數物件上運作。不過,Underscore 函式並非設計成在「稀疏」陣列上運作。

first_.first(array, [n]) 別名:headtake 來源
傳回陣列的第一個元素。傳遞n會傳回陣列的前n個元素。

_.first([5, 4, 3, 2, 1]);
=> 5

initial_.initial(array, [n]) 來源
傳回陣列的全部內容,但不包含最後一個項目。在引數物件上特別好用。傳遞n以從結果中排除最後n個元素。

_.initial([5, 4, 3, 2, 1]);
=> [5, 4, 3, 2]

last_.last(array, [n]) 來源
傳回陣列的最後一個元素。傳遞n會傳回陣列的最後n個元素。

_.last([5, 4, 3, 2, 1]);
=> 1

rest_.rest(array, [index]) 別名:tail, drop 來源
傳回陣列中元素的其餘部分。傳遞一個索引,從該索引開始傳回陣列的值。

_.rest([5, 4, 3, 2, 1]);
=> [4, 3, 2, 1]

flatten_.flatten(array, [depth]) 來源
壓平巢狀陣列。如果您傳遞 true1 作為深度,陣列只會壓平一層。傳遞更大的數字會導致壓平更深入地進入巢狀層級。省略深度參數,或傳遞 falseInfinity,會將陣列壓平到最深的巢狀層級。

_.flatten([1, [2], [3, [[4]]]]);
=> [1, 2, 3, 4];

_.flatten([1, [2], [3, [[4]]]], true);
=> [1, 2, 3, [[4]]];

_.flatten([1, [2], [3, [[4]]]], 2);
=> [1, 2, 3, [4]];

without_.without(array, *values) 來源
傳回陣列的副本,其中所有的執行個體都已移除。

_.without([1, 2, 1, 0, 3, 1, 4], 0, 1);
=> [2, 3, 4]

union_.union(*arrays) 來源
計算傳入陣列的聯集:出現在一個或多個陣列中的一系列唯一項目,按順序排列。

_.union([1, 2, 3], [101, 2, 1, 10], [2, 1]);
=> [1, 2, 3, 101, 10]

intersection_.intersection(*arrays) 來源
計算所有陣列的交集值清單。結果中的每個值都存在於每個陣列中。

_.intersection([1, 2, 3], [101, 2, 1, 10], [2, 1]);
=> [1, 2]

difference_.difference(array, *others) 來源
類似於without,但傳回陣列中不存在於其他陣列中的值。

_.difference([1, 2, 3, 4, 5], [5, 2, 10]);
=> [1, 3, 4]

uniq_.uniq(array, [isSorted], [iteratee]) 別名:unique 來源
使用 === 來測試物件相等性,產生 陣列 的無重複版本。特別是,只保留每個值的第一次出現。如果您事先知道 陣列 已排序,傳遞 trueisSorted 將會執行更快的演算法。如果您想根據轉換計算唯一項目,請傳遞 iteratee 函式。

_.uniq([1, 2, 1, 4, 1, 3]);
=> [1, 2, 4, 3]

zip_.zip(*arrays) 來源
將每個 陣列 的值與對應位置的值合併在一起。當您有透過比對陣列索引來協調的不同資料來源時,這會很有用。

_.zip(['moe', 'larry', 'curly'], [30, 40, 50], [true, false, false]);
=> [["moe", 30, true], ["larry", 40, false], ["curly", 50, false]]

unzip_.unzip(array) 別名:transpose 來源
zip 的相反。給定一個陣列的陣列,傳回一系列新的陣列,第一個包含輸入陣列中所有第一個元素,第二個包含所有第二個元素,依此類推。如果您使用的是巢狀陣列的矩陣,這可以用來轉置矩陣。

_.unzip([["moe", 30, true], ["larry", 40, false], ["curly", 50, false]]);
=> [['moe', 'larry', 'curly'], [30, 40, 50], [true, false, false]]

object_.object(list, [values]) 來源
將陣列轉換為物件。傳遞單一 [key, value] 成對的清單,或清單的鍵和清單的值。成對傳遞是 成對 的相反。如果存在重複的鍵,則最後一個值會獲勝。

_.object(['moe', 'larry', 'curly'], [30, 40, 50]);
=> {moe: 30, larry: 40, curly: 50}

_.object([['moe', 30], ['larry', 40], ['curly', 50]]);
=> {moe: 30, larry: 40, curly: 50}

chunk_.chunk(array, length) 來源
陣列區塊化為多個陣列,每個陣列包含長度或更少的項目。

var partners = _.chunk(_.shuffle(kindergarten), 2);
=> [["Tyrone", "Elie"], ["Aidan", "Sam"], ["Katrina", "Billie"], ["Little Timmy"]]

indexOf_.indexOf(array, value, [isSorted]) 來源
傳回陣列中可以找到的索引,或者如果陣列中不存在值,則傳回-1。如果您使用的是大型陣列,並且知道陣列已經排序,請傳遞 trueisSorted 以使用更快的二元搜尋 ... 或者,傳遞數字作為第三個參數,以便在給定索引之後的陣列中尋找第一個匹配值。如果 isSortedtrue,則此函數使用運算子 < (註解).

_.indexOf([1, 2, 3], 2);
=> 1

lastIndexOf_.lastIndexOf(array, value, [fromIndex]) 來源
傳回陣列中最後出現的索引,或者如果值不存在,則傳回-1。傳遞fromIndex 以在給定索引處開始搜尋。

_.lastIndexOf([1, 2, 3, 1, 2, 3], 2);
=> 4

sortedIndex_.sortedIndex(array, value, [iteratee], [context]) 來源
使用二元搜尋來決定應該將插入陣列中以維持陣列的排序順序的最小索引。如果提供了反覆運算器函式,它將用於計算每個值的排序排名,包括您傳遞的。反覆運算器也可以是依其排序的屬性的字串名稱(例如 length)。此函式使用運算子 <註解)。

_.sortedIndex([10, 20, 30, 40, 50], 35);
=> 3

var stooges = [{name: 'moe', age: 40}, {name: 'curly', age: 60}];
_.sortedIndex(stooges, {name: 'larry', age: 50}, 'age');
=> 1

findIndex_.findIndex(array, predicate, [context]) 來源
類似於 _.indexOf,傳回謂詞真值測試通過的第一個索引;否則傳回 -1

_.findIndex([4, 6, 8, 12], isPrime);
=> -1 // not found
_.findIndex([4, 6, 7, 12], isPrime);
=> 2

findLastIndex_.findLastIndex(array, predicate, [context]) 來源
類似於 _.findIndex,但反向反覆運算陣列,傳回最接近結尾處,且謂詞真值測試通過的索引。

var users = [{'id': 1, 'name': 'Bob', 'last': 'Brown'},
             {'id': 2, 'name': 'Ted', 'last': 'White'},
             {'id': 3, 'name': 'Frank', 'last': 'James'},
             {'id': 4, 'name': 'Ted', 'last': 'Jones'}];
_.findLastIndex(users, {
  name: 'Ted'
});
=> 3

range_.range([start], stop, [step]) 來源
一個用於建立彈性編號整數清單的功能,適用於 eachmap 迴圈。start 如果省略,預設為 0step 如果 startstop 之前,預設為 1,否則為 -1。傳回一個從 start(包含)到 stop(不包含)的整數清單,以 step 的值遞增(或遞減)。

_.range(10);
=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
_.range(1, 11);
=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
_.range(0, 30, 5);
=> [0, 5, 10, 15, 20, 25]
_.range(0, -10, -1);
=> [0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
_.range(0);
=> []

函式(呃,啊)函式

bind_.bind(function, object, *arguments) 來源
將一個 function 繫結到一個 object,表示每當呼叫該函式時,this 的值將會是 object。選擇性地傳遞 argumentsfunction 以預先填入,也稱為 部分應用。對於不帶有內容繫結的部分應用,請使用 partial

var func = function(greeting){ return greeting + ': ' + this.name };
func = _.bind(func, {name: 'moe'}, 'hi');
func();
=> 'hi: moe'

bindAll_.bindAll(object, *methodNames) 來源
繫結 object 上由 methodNames 指定的多個方法,以便在呼叫這些方法時在該物件的內容中執行。對於繫結將用作事件處理常式的函式非常方便,否則這些函式會以相當無用的 this 呼叫。methodNames 是必要的。

var buttonView = {
  label  : 'underscore',
  onClick: function(){ alert('clicked: ' + this.label); },
  onHover: function(){ console.log('hovering: ' + this.label); }
};
_.bindAll(buttonView, 'onClick', 'onHover');
// When the button is clicked, this.label will have the correct value.
jQuery('#underscore_button').on('click', buttonView.onClick);

partial_.partial(function, *arguments) 來源
透過填入任意數量的 arguments 來部分應用一個函式,而不變更其動態 this 值。是 bind 的近親。你可以在 arguments 清單中傳遞 _,以指定不應預先填入,但保留在呼叫時提供的一個引數。注意:如果你同時需要 _ 佔位符和 this 繫結,請同時使用 _.partial_.bind

var subtract = function(a, b) { return b - a; };
sub5 = _.partial(subtract, 5);
sub5(20);
=> 15

// Using a placeholder
subFrom20 = _.partial(subtract, _, 20);
subFrom20(5);
=> 15

memoize_.memoize(function, [hashFunction]) 來源
記憶化給定的函數,快取計算結果。對於加速執行速度較慢的運算很有用。如果傳遞一個選用的hashFunction,它會用於計算儲存結果的雜湊金鑰,根據原始函數的參數。預設的hashFunction僅使用記憶化函數的第一個參數作為金鑰。記憶化值的快取可作為傳回函數上的cache屬性。

var fibonacci = _.memoize(function(n) {
  return n < 2 ? n: fibonacci(n - 1) + fibonacci(n - 2);
});

delay_.delay(function, wait, *arguments) 來源
很像setTimeout,在wait毫秒後呼叫function。如果您傳遞選用的arguments,它們會在呼叫function時轉發給function

var log = _.bind(console.log, console);
_.delay(log, 1000, 'logged later');
=> 'logged later' // Appears after one second.

defer_.defer(function, *arguments) 來源
延遲呼叫function,直到目前的呼叫堆疊清除,類似於使用延遲時間為 0 的setTimeout。對於在不阻擋 UI 執行緒更新的情況下,分批執行昂貴的運算或 HTML 呈現很有用。如果您傳遞選用的arguments,它們會在呼叫function時轉發給function

_.defer(function(){ alert('deferred'); });
// Returns from the function before the alert runs.

throttle_.throttle(function, wait, [options]) 來源
建立並傳回傳遞函式的節流版本,當重複呼叫時,只會在每隔等待毫秒實際呼叫一次原始函式。對於以比您能跟上的速度更快的速率限制事件很有用。

預設情況下,節流會在您第一次呼叫函式時執行函式,而且,如果您在等待期間再次呼叫函式,則會在該期間結束後立即執行。如果您想要停用前緣呼叫,請傳遞{leading: false},如果您想要停用後緣執行,請傳遞
{trailing: false}.

var throttled = _.throttle(updatePosition, 100);
$(window).scroll(throttled);

如果您需要取消排程的節流,您可以在節流函式上呼叫.cancel()

去抖動_.debounce(function, wait, [immediate]) source
建立並傳回傳遞函式的去抖動版本,它會延後執行,直到自上次呼叫後經過等待毫秒。對於實作輸入停止後才應該發生的行為很有用。例如:呈現 Markdown 註解的預覽、在視窗停止調整大小後重新計算版面,等等。

等待區間結束時,函式將會使用最近傳遞給去抖動函式的引數來呼叫。

傳遞 trueimmediate 參數以導致 debouncewait 間隔的開始邊緣觸發函式,而不是結束邊緣。在像防止「提交」按鈕的意外雙擊第二次觸發的情況下很有用。

var lazyLayout = _.debounce(calculateLayout, 300);
$(window).resize(lazyLayout);

如果你需要取消已排程的 debounce,你可以對 debounced 函式呼叫 .cancel()

once_.once(function) 來源
建立函式的版本,只能呼叫一次。重複呼叫修改的函式不會產生任何效果,傳回原始呼叫的值。對於初始化函式很有用,而不是必須設定布林旗標,然後稍後檢查它。

var initialize = _.once(createApplication);
initialize();
initialize();
// Application is only created once.

after_.after(count, function) 來源
建立 function 的包裝器,一開始不執行任何動作。從 count 第次呼叫開始,它開始實際呼叫 function。對於群組非同步回應很有用,在這種情況下,你希望確保所有非同步呼叫都已完成,然後再繼續進行。

var renderNotes = _.after(notes.length, render);
_.each(notes, function(note) {
  note.asyncSave({success: renderNotes});
});
// renderNotes is run once, after all notes have saved.

before_.before(count, function) 來源
建立 function 的包裝器,將其傳回值記憶化。從 count 第次呼叫開始,最後一次呼叫的記憶化結果會立即傳回,而不是再次呼叫 function。因此,包裝器會呼叫 function 最多 count - 1 次。

var monthlyMeeting = _.before(3, askForRaise);
monthlyMeeting();
monthlyMeeting();
monthlyMeeting();
// the result of any subsequent calls is the same as the second call

wrap_.wrap(function, wrapper) 來源
將第一個函數封裝在封裝函數內,並將其傳遞為第一個參數。這允許封裝函數執行之前和之後執行程式碼,調整參數,並有條件地執行它。

var hello = function(name) { return "hello: " + name; };
hello = _.wrap(hello, function(func) {
  return "before, " + func("moe") + ", after";
});
hello();
=> 'before, hello: moe, after'

negate_.negate(predicate) 來源
傳回一個新的predicate函數的否定版本。

var isFalsy = _.negate(Boolean);
_.find([-2, -1, 0, 1, 2], isFalsy);
=> 0

compose_.compose(*functions) 來源
傳回一個函數清單的組合,其中每個函數使用後續函數的傳回值。在數學術語中,組合函數f()g()h()會產生f(g(h()))

var greet    = function(name){ return "hi: " + name; };
var exclaim  = function(statement){ return statement.toUpperCase() + "!"; };
var welcome = _.compose(greet, exclaim);
welcome('moe');
=> 'hi: MOE!'

restArguments_.restArguments(function, [startIndex]) 來源
傳回函數的一個版本,當呼叫時,會接收從startIndex開始的所有參數,並收集到一個陣列中。如果您沒有傳遞明確的startIndex,它將透過查看函數本身的參數數量來決定。類似於 ES6 的rest 參數語法

var raceResults = _.restArguments(function(gold, silver, bronze, everyoneElse) {
  _.each(everyoneElse, sendConsolations);
});

raceResults("Dopey", "Grumpy", "Happy", "Sneezy", "Bashful", "Sleepy", "Doc");

物件函數

keys_.keys(object) 來源
擷取物件本身所有可列舉屬性的名稱。

_.keys({one: 1, two: 2, three: 3});
=> ["one", "two", "three"]

allKeys_.allKeys(object) 原始碼
擷取object所有自身和繼承的屬性名稱。

function Stooge(name) {
  this.name = name;
}
Stooge.prototype.silly = true;
_.allKeys(new Stooge("Moe"));
=> ["name", "silly"]

values_.values(object) 原始碼
傳回object所有自身屬性的值。

_.values({one: 1, two: 2, three: 3});
=> [1, 2, 3]

mapObject_.mapObject(object, iteratee, [context]) 原始碼
類似於map,但適用於物件。依序轉換物件中每個屬性的值。

_.mapObject({start: 5, end: 12}, function(val, key) {
  return val + 5;
});
=> {start: 10, end: 17}

pairs_.pairs(object) 原始碼
將物件轉換成[key, value]配對的清單。與object相反。

_.pairs({one: 1, two: 2, three: 3});
=> [["one", 1], ["two", 2], ["three", 3]]

invert_.invert(object) 原始碼
傳回object的副本,其中 key 已變成 value,而 value 已變成 key。要執行此動作,物件中的所有值都必須是唯一的,且可序列化成字串。

_.invert({Moe: "Moses", Larry: "Louis", Curly: "Jerome"});
=> {Moses: "Moe", Louis: "Larry", Jerome: "Curly"};

create_.create(prototype, props) 原始碼
使用指定的原型建立新的物件,並選擇性地附加props作為自身屬性。基本上就是Object.create,但沒有所有屬性描述符的複雜性。

var moe = _.create(Stooge.prototype, {name: "Moe"});

functions_.functions(object) 別名:methods 原始碼
傳回物件中所有方法名稱的已排序清單,也就是物件中所有函式屬性的名稱。

_.functions(_);
=> ["all", "any", "bind", "bindAll", "clone", "compact", "compose" ...

findKey_.findKey(object, predicate, [context]) 來源
類似 _.findIndex,但適用於物件中的鍵。傳回predicate 判斷式為真時,對應的,或未定義predicate 會透過 iteratee 轉換,以利簡寫語法。

extend_.extend(destination, *sources) 來源
source 物件中的所有屬性淺層複製到destination 物件,並傳回destination 物件。任何巢狀物件或陣列都將以參照方式複製,而非複製副本。複製順序為依序,因此最後一個 source 會覆寫先前參數中同名的屬性。

_.extend({name: 'moe'}, {age: 50});
=> {name: 'moe', age: 50}

extendOwn_.extendOwn(destination, *sources) 別名:assign 來源
extend 類似,但只會將自己的屬性複製到 destination 物件。

pick_.pick(object, *keys) 來源
傳回object 的副本,僅保留允許的keys(或有效鍵陣列)的值。或者接受一個判斷式,用於指出要挑選哪些鍵。

_.pick({name: 'moe', age: 50, userid: 'moe1'}, 'name', 'age');
=> {name: 'moe', age: 50}
_.pick({name: 'moe', age: 50, userid: 'moe1'}, function(value, key, object) {
  return _.isNumber(value);
});
=> {age: 50}

omit_.omit(object, *keys) 來源
傳回object 的副本,過濾掉不允許的keys(或鍵陣列)。或者接受一個判斷式,用於指出要略過的鍵。

_.omit({name: 'moe', age: 50, userid: 'moe1'}, 'userid');
=> {name: 'moe', age: 50}
_.omit({name: 'moe', age: 50, userid: 'moe1'}, function(value, key, object) {
  return _.isNumber(value);
});
=> {name: 'moe', userid: 'moe1'}

預設值_.defaults(object, *defaults) 來源
在下列 defaults 物件清單中填入第一個現有值後,傳回 object

var iceCream = {flavor: "chocolate"};
_.defaults(iceCream, {flavor: "vanilla", sprinkles: "lots"});
=> {flavor: "chocolate", sprinkles: "lots"}

複製_.clone(object) 來源
建立提供的 object 的淺層複製。任何巢狀物件或陣列都將透過參考複製,而不是複製。

_.clone({name: 'moe'});
=> {name: 'moe'};

點選_.tap(object, interceptor) 來源
使用 object 呼叫 interceptor,然後傳回 object。此方法的主要目的是「點選」方法鏈,以便在鏈中對中間結果執行操作。

_.chain([1,2,3,200])
  .filter(function(num) { return num % 2 == 0; })
  .tap(alert)
  .map(function(num) { return num * num })
  .value();
=> // [2, 200] (alerted)
=> [4, 40000]

轉換為路徑_.toPath(path) 來源
確保 path 是陣列。如果 path 是字串,則會包裝在單一元素陣列中;如果它已經是陣列,則會不修改地傳回。

_.toPath('key');
=> ['key']
_.toPath(['a', 0, 'b']);
=> ['a', 0, 'b'] // (same array)

_.toPathhasgetinvokepropertypropertyOfresult 中內部使用,以及在 iteratee 和所有依賴它的函式中使用,以將深度屬性路徑正規化。如果您想要自訂這個行為,例如啟用類似 Lodash 的字串路徑簡寫,您可以覆寫 _.toPath。請注意,變更 _.toPath 將不可避免地導致某些金鑰無法存取;覆寫時請自行承擔風險。

// Support dotted path shorthands.
var originalToPath = _.toPath;
_.mixin({
  toPath: function(path) {
    return _.isString(path) ? path.split('.') : originalToPath(path);
  }
});
_.get({a: [{b: 5}]}, 'a.0.b');
=> 5

get_.get(object, path, [default]) 來源
傳回 object 的指定屬性。path 可以指定為簡單的鍵,或作為物件鍵或陣列索引的陣列,用於深度屬性擷取。如果屬性不存在或為 undefined,則傳回選用的 default

_.get({a: 10}, 'a');
=> 10
_.get({a: [{b: 2}]}, ['a', 0, 'b']);
=> 2
_.get({a: 10}, 'b', 100);
=> 100

has_.has(object, key) 來源
物件是否包含給定的鍵?與 object.hasOwnProperty(key) 相同,但使用 hasOwnProperty 函式的安全參照,以防它意外地被覆寫

_.has({a: 1, b: 2, c: 3}, "b");
=> true

property_.property(path) 來源
傳回一個函式,它將傳回任何傳入物件的指定屬性。path 可以指定為簡單的鍵,或作為物件鍵或陣列索引的陣列,用於深度屬性擷取。

var stooge = {name: 'moe'};
'moe' === _.property('name')(stooge);
=> true

var stooges = {moe: {fears: {worst: 'Spiders'}}, curly: {fears: {worst: 'Moe'}}};
var curlysWorstFear = _.property(['curly', 'fears', 'worst']);
curlysWorstFear(stooges);
=> 'Moe'

propertyOf_.propertyOf(object) 來源
_.property 的反函式。取得一個物件並傳回一個函式,它將傳回所提供屬性的值。

var stooge = {name: 'moe'};
_.propertyOf(stooge)('name');
=> 'moe'

matcher_.matcher(attrs) 別名:matches 來源
傳回一個謂詞函數,用來判斷傳入的物件是否包含所有在 attrs 中的鍵值屬性。

var ready = _.matcher({selected: true, visible: true});
var readyToGoList = _.filter(list, ready);

isEqual_.isEqual(object, other) 來源
對兩個物件執行最佳化的深度比較,以判斷它們是否應該被視為相等。

var stooge = {name: 'moe', luckyNumbers: [13, 27, 34]};
var clone  = {name: 'moe', luckyNumbers: [13, 27, 34]};
stooge == clone;
=> false
_.isEqual(stooge, clone);
=> true

isMatch_.isMatch(object, properties) 來源
告訴你 properties 中的鍵和值是否包含在 object 中。

var stooge = {name: 'moe', age: 32};
_.isMatch(stooge, {age: 32});
=> true

isEmpty_.isEmpty(collection) 來源
如果 collection 沒有元素,則傳回 true。對於字串和類陣列物件,_.isEmpty 會檢查長度屬性是否為 0。對於其他物件,如果物件沒有可列舉的自身屬性,則傳回 true。請注意,根據此定義,原始數字、布林值和符號永遠都是空的。

_.isEmpty([1, 2, 3]);
=> false
_.isEmpty({});
=> true

isElement_.isElement(object) 來源
如果 object 是 DOM 元素,則傳回 true

_.isElement(jQuery('body')[0]);
=> true

isArray_.isArray(object) 來源
如果 object 是陣列,則傳回 true

(function(){ return _.isArray(arguments); })();
=> false
_.isArray([1,2,3]);
=> true

isObject_.isObject(value) 來源
如果 value 是物件,則傳回 true。請注意,JavaScript 陣列和函數是物件,而(一般的)字串和數字則不是。

_.isObject({});
=> true
_.isObject(1);
=> false

isArguments_.isArguments(object) 來源
如果 object 是 Arguments 物件,則傳回 true

(function(){ return _.isArguments(arguments); })(1, 2, 3);
=> true
_.isArguments([1,2,3]);
=> false

isFunction_.isFunction(object) 來源
如果 object 是函式,則傳回 true

_.isFunction(alert);
=> true

isString_.isString(object) 來源
如果 object 是字串,則傳回 true

_.isString("moe");
=> true

isNumber_.isNumber(object) 來源
如果 object 是數字(包括 NaN),則傳回 true

_.isNumber(8.4 * 5);
=> true

isFinite_.isFinite(object) 來源
如果 object 是有限數字,則傳回 true

_.isFinite(-101);
=> true

_.isFinite(-Infinity);
=> false

isBoolean_.isBoolean(object) 來源
如果 objecttruefalse,則傳回 true

_.isBoolean(null);
=> false

isDate_.isDate(object) 來源
如果 object 是日期,則傳回 true

_.isDate(new Date());
=> true

isRegExp_.isRegExp(object) 來源
如果 object 是正規表示法,則傳回 true

_.isRegExp(/moe/);
=> true

isError_.isError(object) 來源
如果 object 繼承自 Error,則傳回 true

try {
  throw new TypeError("Example");
} catch (o_O) {
  _.isError(o_O);
}
=> true

isSymbol_.isSymbol(object) 來源
如果 objectSymbol,則傳回 true

_.isSymbol(Symbol());
=> true

isMap_.isMap(object) 來源
如果 objectMap,則傳回 true

_.isMap(new Map());
=> true

isWeakMap_.isWeakMap(object) 來源
如果 objectWeakMap,則傳回 true

_.isWeakMap(new WeakMap());
=> true

isSet_.isSet(object) 來源
如果 objectSet,則傳回 true

_.isSet(new Set());
=> true

isWeakSet_.isWeakSet(object) 來源
如果 objectWeakSet,則傳回 true

_.isWeakSet(WeakSet());
=> true

isArrayBuffer_.isArrayBuffer(object) 來源
如果 objectArrayBuffer,則傳回 true

_.isArrayBuffer(new ArrayBuffer(8));
=> true

isDataView_.isDataView(object) 來源
如果 objectDataView,則傳回 true

_.isDataView(new DataView(new ArrayBuffer(8)));
=> true

isTypedArray_.isTypedArray(object) 來源
如果 objectTypedArray,則傳回 true

_.isTypedArray(new Int8Array(8));
=> true

isNaN_.isNaN(object) 來源
如果 objectNaN,則傳回 true
注意:這與原生 isNaN 函數不同,後者也會對許多其他非數字值傳回 true,例如 undefined

_.isNaN(NaN);
=> true
isNaN(undefined);
=> true
_.isNaN(undefined);
=> false

isNull_.isNull(object) 來源
如果 object 的值為 null,則傳回 true

_.isNull(null);
=> true
_.isNull(undefined);
=> false

isUndefined_.isUndefined(value) 來源
如果 valueundefined,則傳回 true

_.isUndefined(window.missingVariable);
=> true

工具函數

noConflict_.noConflict() 來源
_ 全域變數的控制權交還給先前擁有者。傳回對 Underscore 物件的參考。

var underscore = _.noConflict();

如果您使用 EcmaScript 6、AMD 或 CommonJS 模組系統來匯入 Underscore,則不會有 _.noConflict 函數。

identity_.identity(value) 來源
傳回與引數相同的數值。在數學中:f(x) = x
此函數看似無用,但 Underscore 中會將其用作預設迭代器。

var stooge = {name: 'moe'};
stooge === _.identity(stooge);
=> true

constant_.constant(value) 來源
建立一個函數,傳回與 _.constant 引數相同的數值。

var stooge = {name: 'moe'};
stooge === _.constant(stooge)();
=> true

noop_.noop() 來源
不論傳入什麼引數,都傳回 undefined。可用作選用回呼引數的預設值。

obj.initialize = _.noop;

times_.times(n, iteratee, [context]) 來源
呼叫給定的 iteratee 函式 n 次。每次呼叫 iteratee 都會呼叫 index 引數。產生已傳回值的陣列。

_.times(3, function(n){ genie.grantWishNumber(n); });

random_.random(min, max) 來源
傳回介於 minmax 之間的亂數整數(含)。如果您只傳遞一個引數,則會傳回介於 0 和該數字之間的數字。

_.random(0, 100);
=> 42

mixin_.mixin(object) 來源
允許您使用自己的公用程式函式來延伸 Underscore。傳遞 {name: function} 定義的雜湊,以將您的函式新增至 Underscore 物件,以及 OOP 包裝器。傳回 Underscore 物件以利於串連。

_.mixin({
  capitalize: function(string) {
    return string.charAt(0).toUpperCase() + string.substring(1).toLowerCase();
  }
});
_("fabio").capitalize();
=> "Fabio"

iteratee_.iteratee(value, [context]) 來源
產生可套用至集合中每個元素的回呼。 _.iteratee 支援許多常見回呼使用案例的簡寫語法。根據 value 的類型,_.iteratee 會傳回

// No value
_.iteratee();
=> _.identity()

// Function
_.iteratee(function(n) { return n * 2; });
=> function(n) { return n * 2; }

// Object
_.iteratee({firstName: 'Chelsea'});
=> _.matcher({firstName: 'Chelsea'});

// Anything else
_.iteratee('firstName');
=> _.property('firstName');

下列 Underscore 方法會透過 _.iteratee 轉換它們的謂詞:countByeveryfilterfindfindIndexfindKeyfindLastIndexgroupByindexBymapmapObjectmaxminpartitionrejectsomesortBysortedIndexuniq

如果你想要額外的或不同的簡寫語法,你可以用你自己的自訂函數覆寫 _.iteratee

// Support `RegExp` predicate shorthand.
var builtinIteratee = _.iteratee;
_.iteratee = function(value, context) {
  if (_.isRegExp(value)) return function(obj) { return value.test(obj) };
  return builtinIteratee(value, context);
};

uniqueId_.uniqueId([prefix]) 來源
為需要一個的客戶端模型或 DOM 元素產生一個全域唯一的 ID。如果傳遞了 prefix,ID 會附加在它後面。

_.uniqueId('contact_');
=> 'contact_104'

escape_.escape(string) 來源
轉譯字串以插入 HTML 中,取代 &<>"`' 字元。

_.escape('Curly, Larry & Moe');
=> "Curly, Larry &amp; Moe"

unescape_.unescape(string) 來源
escape 的反向操作,將 &amp;&lt;&gt;&quot;&#x60;&#x27; 替換成它們未轉譯的對應字元。

_.unescape('Curly, Larry &amp; Moe');
=> "Curly, Larry & Moe"

result_.result(object, property, [defaultValue]) 來源
如果命名屬性的值為函數,則以物件為內容呼叫它;否則,傳回它。如果提供預設值,且屬性不存在或未定義,則會傳回預設值。如果 defaultValue 為函數,則會傳回其結果。

var object = {cheese: 'crumpets', stuff: function(){ return 'nonsense'; }};
_.result(object, 'cheese');
=> "crumpets"
_.result(object, 'stuff');
=> "nonsense"
_.result(object, 'meat', 'ham');
=> "ham"

now_.now() 來源
使用執行時期中可用的最快方法,傳回目前時間的整數時間戳記。對於實作計時/動畫函數很有用。

_.now();
=> 1392066795351

template_.template(templateString, [settings]) 來源
將 JavaScript 範本編譯成可評估用於呈現的函數。對於從 JSON 資料來源呈現複雜的 HTML 位元很有用。範本函數可以使用 <%= … %> 內插值,也可以使用 <% … %> 執行任意 JavaScript 程式碼。如果您想要內插值,並讓它成為 HTML 逃逸,請使用 <%- … %>。當您評估範本函數時,請傳入一個資料物件,其屬性對應於範本的自由變數。設定引數應該是一個雜湊,包含任何應該覆寫的 _.templateSettings

var compiled = _.template("hello: <%= name %>");
compiled({name: 'moe'});
=> "hello: moe"

var template = _.template("<b><%- value %></b>");
template({value: '<script>'});
=> "<b>&lt;script&gt;</b>"

您也可以在 JavaScript 程式碼中使用 print。這有時比使用 <%= ... %> 方便。

var compiled = _.template("<% print('Hello ' + epithet); %>");
compiled({epithet: "stooge"});
=> "Hello stooge"

如果 ERB 風格的界定符號不符合您的喜好,您可以變更 Underscore 的範本設定,使用不同的符號來設定內插程式碼。定義一個 interpolate 正規表示式,以符合應逐字內插的表達式,一個 escape 正規表示式,以符合應在經過 HTML 轉譯後插入的表達式,以及一個 evaluate 正規表示式,以符合應在不插入結果字串的情況下評估的表達式。請注意,如果您的範本部分符合多個這些正規表示式,則會依下列優先順序套用第一個正規表示式:(1) escape,(2) interpolate,(3) evaluate。您可以定義或省略這三者的任何組合。例如,若要執行 Mustache.js 風格的範本處理

_.templateSettings = {
  interpolate: /\{\{(.+?)\}\}/g
};

var template = _.template("Hello {{ name }}!");
template({name: "Mustache"});
=> "Hello Mustache!"

預設情況下,template 會透過 with 陳述式將資料中的值置於區域範圍內。不過,您可以使用 variable 設定指定單一變數名稱。這可以大幅提升範本能夠呈現的速度。

_.template("Using 'with': <%= data.answer %>", {variable: 'data'})({answer: 'no'});
=> "Using 'with': no"

預編譯範本在您除錯無法重現的錯誤時,可以提供很大的幫助。這是因為預編譯範本可以提供行號和堆疊追蹤,這是在用戶端編譯範本時無法做到的。source 屬性可在編譯的範本函式上使用,以進行輕鬆的預編譯。

<script>
  JST.project = <%= _.template(jstText).source %>;
</script>

物件導向風格

您可以使用物件導向或函式風格的 Underscore,視您的喜好而定。下列兩行程式碼是將數字清單加倍的相同方式。 source, source

_.map([1, 2, 3], function(n){ return n * 2; });
_([1, 2, 3]).map(function(n){ return n * 2; });

串接

呼叫 chain 會導致所有後續的方法呼叫傳回包裝物件。當您完成計算時,呼叫 value 以擷取最終值。以下是串連 map/flatten/reduce 的範例,以取得歌曲中每個字詞的字數。

var lyrics = [
  {line: 1, words: "I'm a lumberjack and I'm okay"},
  {line: 2, words: "I sleep all night and I work all day"},
  {line: 3, words: "He's a lumberjack and he's okay"},
  {line: 4, words: "He sleeps all night and he works all day"}
];

_.chain(lyrics)
  .map(function(line) { return line.words.split(' '); })
  .flatten()
  .reduce(function(counts, word) {
    counts[word] = (counts[word] || 0) + 1;
    return counts;
  }, {})
  .value();

=> {lumberjack: 2, all: 4, night: 2 ... }

此外,陣列原型方法 會透過串連的底線物件代理,因此您可以將 reversepush 滑入串連中,並繼續修改陣列。

chain_.chain(obj) 來源
傳回包裝物件。呼叫此物件上的方法會持續傳回包裝物件,直到呼叫 value 為止。

var stooges = [{name: 'curly', age: 25}, {name: 'moe', age: 21}, {name: 'larry', age: 23}];
var youngest = _.chain(stooges)
  .sortBy(function(stooge){ return stooge.age; })
  .map(function(stooge){ return stooge.name + ' is ' + stooge.age; })
  .first()
  .value();
=> "moe is 21"

value_.chain(obj).value() 來源
萃取包裝物件的值。

_.chain([1, 2, 3]).reverse().value();
=> [3, 2, 1]

Underscore.lua,適用於兩種語言的函式 Lua 移植。包含 OOP 包裝和串連。(來源

Dollar.swift,許多 Underscore.js 函式及更多內容的 Swift 移植。(來源

Underscore.m,許多 Underscore.js 函式的 Objective-C 移植,使用鼓勵鏈接的語法。(來源

_.m,替代的 Objective-C 移植,嘗試更貼近原始的 Underscore.js API。(來源

Underscore.php,適用於兩種語言的函式的 PHP 移植。針對 PHP 5.4 量身打造,並考慮到資料類型容錯。(來源

Underscore-perl,許多 Underscore.js 函式的 Perl 移植,針對 Perl 雜湊和陣列。(來源

Underscore.cfc,許多 Underscore.js 函式的 Coldfusion 移植。(來源

Underscore.string,一個 Underscore 擴充,新增字串操作函式:trimstartsWithcontainscapitalizereversesprintf 等。

Underscore-java,適用於兩種語言的函式的 Java 移植。包含 OOP 封裝和鏈接。(來源

Ruby 的 Enumerable 模組。

Prototype.js,提供 JavaScript 集合函式,其方式最接近 Ruby 的 Enumerable。

Oliver Steele 的 Functional JavaScript,包含全面的高階函式支援以及字串 lambda。

Michael Aufreiter 的 Data.js,一個 JavaScript 的資料處理 + 持久化函式庫。

Python 的 itertools

PyToolz,一個 Python 移植,擴充 itertools 和 functools 以包含大部分的 Underscore API。

Funcy,一個實用的 Python 函式輔助程式集合,部分靈感來自 Underscore。

備註

關於在 Underscore 中使用 <
依賴順序的 Underscore 函式,例如 _.sortBy_.sortedIndex,使用 JavaScript 內建的 關係運算子,特別是「小於」運算子 <。了解這些運算子僅對數字和字串有意義非常重要。你可以傳遞任何值給它們,但 JavaScript 會在執行實際比較之前,先將運算元轉換為字串或數字。如果你傳遞一個無法有意義地轉換為字串或數字的運算元,它預設會變成 NaN。這個值無法排序。

理想情況下,你排序的值應該全部是(有意義地可轉換為)字串或全部是(有意義地可轉換為)數字。如果不是這種情況,你有兩個選項

變更記錄

1.13.62022 年 9 月 24 日Diff文件
版本 1.13.5 的熱修補程式,用於從 package.json 中移除 postinstall 腳本,這意外中斷了許多人的建置。

1.13.52022 年 9 月 23 日Diff文件

1.13.42022 年 6 月 2 日差異文件

1.13.32022 年 4 月 23 日差異文件

1.13.22021 年 12 月 16 日差異文件

1.13.12021 年 4 月 15 日差異文件

1.13.02021 年 4 月 9 日Diff文件

1.13.0-32021 年 3 月 31 日Diff文件

1.13.0-22021 年 3 月 15 日Diff文件

1.12.12021 年 3 月 15 日Diff文件

1.13.0-12021 年 3 月 11 日Diff文件

1.13.0-02021 年 3 月 9 日Diff文件

1.12.02020 年 11 月 24 日Diff文件

1.11.02020 年 8 月 28 日差異文件文章

1.10.22020 年 3 月 30 日差異文件

1.10.12020 年 3 月 30 日差異文件

1.10.02020 年 3 月 30 日差異文件

1.9.22020 年 1 月 6 日Diff文件

1.9.12018 年 5 月 31 日Diff文件

1.9.02018 年 4 月 18 日Diff文件

1.8.32015 年 4 月 2 日Diff文件

1.8.22015 年 2 月 22 日Diff文件

1.8.12015 年 2 月 19 日Diff文件

1.8.02015 年 2 月 19 日Diff文件

1.7.02014 年 8 月 26 日Diff文件

1.6.02014 年 2 月 10 日差異文件

1.5.22013 年 9 月 7 日Diff文件

1.5.12013 年 7 月 8 日Diff文件

1.5.02013 年 7 月 6 日Diff文件

1.4.42013 年 1 月 30 日差異文件

1.4.32012 年 12 月 4 日Diff文件

1.4.22012 年 10 月 6 日Diff文件

1.4.12012 年 10 月 1 日Diff文件

1.4.02012 年 9 月 27 日Diff文件

1.3.32012 年 4 月 10 日比較文件

1.3.12012 年 1 月 23 日比較文件

1.3.02012 年 1 月 11 日Diff文件

1.2.42012 年 1 月 4 日Diff文件

1.2.32011 年 12 月 7 日Diff文件

1.2.22011 年 11 月 14 日Diff文件

1.2.12011 年 10 月 24 日Diff文件

1.2.02011 年 10 月 5 日Diff文件

1.1.72011 年 7 月 13 日Diff文件
新增 _.groupBy,它會將一個集合彙總成群組,其中包含類似的項目。新增 _.union_.difference,以補充(已重新命名)_.intersection。針對稀疏陣列支援的各種改進。_.toArray 現在會傳回一個複製,如果直接傳遞一個陣列。_.functions 現在也會傳回原型鏈中存在的函數名稱。

1.1.62011 年 4 月 18 日Diff文件
新增 _.after,它會傳回一個函數,該函數僅在第一次被呼叫指定次數後才會執行。_.invoke 現在可以接受直接函數參考。_.every 現在需要傳遞一個迭代器函數,這反映了 ES5 API。_.extend 在值未定義時不再複製鍵。_.bind 現在在嘗試繫結未定義值時會產生錯誤。

1.1.52011 年 3 月 20 日Diff文件
新增一個 _.defaults 函數,用於合併表示預設選項的 JS 物件。新增一個 _.once 函數,用於製造應該只執行一次的函數。_.bind 現在會委派給本機 ES5 版本(如果可用)。_.keys 現在在用於非物件值時會擲回錯誤,就像在 ES5 中一樣。修正了 _.keys 在用於稀疏陣列時遇到的錯誤。

1.1.42011 年 1 月 9 日Diff文件
當傳遞 null 作為值時,改進與 ES5 陣列方法的相容性。 _.wrap 現在正確設定包裝函式的 this_.indexOf 現在採用一個選用旗標,用於在保證已排序的陣列中尋找插入索引。避免使用 .callee,以允許 _.isArray 在 ES5 的嚴格模式中正常運作。

1.1.32010 年 12 月 1 日Diff文件
在 CommonJS 中,現在只需使用
var _ = require("underscore") 即可需要 Underscore。新增 _.throttle_.debounce 函式。移除 _.breakLoop,改用 ES5 風格的不可中斷 each 實作 — 這移除了 try/catch,而且現在您將獲得更好的堆疊追蹤,以追蹤在 Underscore 迭代器中引發的例外。改進 isType 函式系列,以提升與 Internet Explorer 主機物件的互通性。 _.template 現在正確跳脫範本中的反斜線。改進 _.reduce 與 ES5 版本的相容性:如果您未傳遞初始值,則會使用集合中的第一個項目。 _.each 不再傳回迭代的集合,以提升與 ES5 的 forEach 的一致性。

1.1.22010 年 10 月 15 日Diff文件
修正 _.contains,它錯誤地指向 _.intersect,而不是像它應該做的那樣指向 _.include。新增 _.unique 作為 _.uniq 的別名。

1.1.12010 年 10 月 5 日Diff文件
改善 _.template 的速度,以及它對多行內插的處理。Ryan Tenney 為許多 Underscore 函數貢獻了最佳化。現在提供有註解的原始碼版本。

1.1.02010 年 8 月 18 日Diff文件
_.reduce 的方法簽章已變更,以符合 ES5 簽章,而不是 Ruby/Prototype.js 版本。這是一個向後不相容的變更。現在可以不帶任何參數呼叫 _.template,並保留空白。 _.contains_.include 的新別名。

1.0.42010 年 6 月 22 日Diff文件
Andri Möll 貢獻了 _.memoize 函數,它可用於透過快取結果來加速昂貴的重複運算。

1.0.32010 年 6 月 14 日Diff文件
_.isEqual 在比較物件的任何屬性值為 NaN 時回傳 false 的修補程式。技術上來說是正確的作法,但語意上卻有爭議。請注意 NaN 的比較。

1.0.22010 年 3 月 23 日差異文件
修正 _.isArguments 在最近版本的 Opera 中的問題,其將參數物件視為真正的陣列。

1.0.12010 年 3 月 19 日差異文件
修正 _.isEqual 在比較兩個具有相同數量未定義的鍵,但名稱不同的物件時的錯誤。

1.0.02010 年 3 月 18 日差異文件
經過數個月的穩定,Underscore 現在被認為已脫離測試版,版本為 1.0。自 0.6 以來,改進包括 _.isBoolean,以及讓 _.extend 可以採用多個來源物件。

0.6.02010 年 2 月 24 日差異文件
重大版本。結合許多 Mile Frawley 的重構,以在集合函式中進行更安全的鴨子型別,以及更簡潔的內部結構。新的 _.mixin 方法,讓您可以使用自己的公用函式來擴充 Underscore。新增 _.times,其作用與 Ruby 或 Prototype.js 中相同。原生支援 ES5 的 Array.isArrayObject.keys

0.5.82010 年 1 月 28 日差異文件
修正 Underscore 的集合函式,使其再次可以在 NodeListHTMLCollection 上執行,感謝 Justin Tulloss

0.5.72010 年 1 月 20 日差異文件
更安全的 _.isArguments 實作,以及更快速的 _.isNumber
感謝 Jed Schmidt

0.5.62010 年 1 月 18 日差異文件
可自訂 _.template 的分隔符,由 Noah Sloan 貢獻。

0.5.52010 年 1 月 9 日差異文件
修正 MobileSafari 的 OOP 包裝器中,關於 arguments 物件的錯誤。

0.5.42010 年 1 月 5 日差異文件
修正 _.template 中範本字串內有多個單引號的問題。請參閱:Rick Strahl 的部落格文章

0.5.22010 年 1 月 1 日差異文件
根據 Robert Kieffer 的建議,實作新的 isArrayisDateisFunctionisNumberisRegExpisString。這些實作不再進行 Object#toString 比較,而是檢查預期的屬性,安全性較低,但速度提升了十倍以上。因此,大多數其他 Underscore 函式也獲得了輕微的速度提升。Evgeniy Dolzhenko 貢獻了 _.tap類似於 Ruby 1.9,可用於將副作用(例如記錄)注入鏈式呼叫。

0.5.12009 年 12 月 9 日差異文件
新增 _.isArguments 函式。許多小的安全檢查和最佳化由 Noah SloanAndri Möll 貢獻。

0.5.02009 年 12 月 7 日差異文件
[API 變更] _.bindAll 現在將內容物件作為其第一個參數。如果沒有傳遞方法名稱,則所有內容物件的方法都會繫結到它,以啟用鏈接和更輕鬆的繫結。 _.functions 現在只接受一個參數,並傳回其函數屬性的名稱。呼叫 _.functions(_) 將會得到先前的行為。新增 _.isRegExp,因此 isEqual 現在可以測試 RegExp 等式。所有「is」函數都已縮減成單一定義。Karl Guertin 貢獻了修補程式。

0.4.72009 年 12 月 6 日Diff文件
新增 isDateisNaNisNull 以求完整。針對在陣列或日期之間檢查等式時,最佳化 isEqual_.keys 現在快 25%–2X(視您的瀏覽器而定),這會加速仰賴它的函數,例如 _.each

0.4.62009 年 11 月 30 日Diff文件
新增 range 函式,移植自 同名的 Python 函式,用於產生彈性編號的整數清單。原始程式碼補丁由 Kirill Ishanov 貢獻。

0.4.52009 年 11 月 19 日差異文件
新增陣列和引數物件的 rest,並將 first 別名為 head,將 rest 別名為 tail,感謝 Luke Sutton 的程式碼補丁。新增測試,確保所有 Underscore 陣列函式也能在引數物件上運作。

0.4.42009 年 11 月 18 日差異文件
為了一致性,新增 isStringisNumber。修正 _.isEqual(NaN, NaN) 回傳 true(這有爭議)。

0.4.32009 年 11 月 9 日差異文件
開始在支援的瀏覽器中使用原生 StopIteration 物件。修正 Underscore 在 CommonJS 環境中的設定。

0.4.22009 年 11 月 9 日差異文件
為了清晰起見,將拆封函數重新命名為 value

0.4.12009 年 11 月 8 日Diff文件
串聯的 Underscore 物件現在支援陣列原型方法,因此您可以在封裝陣列上執行各種操作,而無需中斷串聯。新增一個 breakLoop 方法,可以在任何 Underscore 迭代過程中中斷。新增一個 isEmpty 函數,適用於陣列和物件。

0.4.02009 年 11 月 7 日Diff文件
現在所有 Underscore 函數都可以以物件導向的方式呼叫,如下所示:_([1, 2, 3]).map(...);。原始修補程式由 Marc-André Cournoyer 提供。封裝物件可以透過多個方法呼叫進行串聯。新增一個 functions 方法,提供 Underscore 中所有函數的排序清單。

0.3.32009 年 10 月 31 日Diff文件
新增 JavaScript 1.8 函數 reduceRight。將其別名設為 foldr,並將 reduce 的別名設為 foldl

0.3.22009 年 10 月 29 日差異文件
現在可以在使用 load("underscore.js") 的原始 Rhino 解譯器上執行。新增 identity 作為公用函式。

0.3.12009 年 10 月 29 日差異文件
現在所有反覆運算子都會在原始集合中傳入第三個引數,與 JavaScript 1.6 的 forEach 相同。反覆運算物件現在會呼叫 (value, key, collection),詳細資訊請參閱 _.each

0.3.02009 年 10 月 29 日差異文件
新增 Dmitry Baranovskiy 的全面最佳化,合併 Kris Kowal 的修補程式,讓 Underscore 符合 CommonJSNarwhal

0.2.02009 年 10 月 28 日差異文件
新增 composelastIndexOf,將 inject 重新命名為 reduce,新增 injectfiltereverysomeforEach 的別名。

0.1.12009 年 10 月 28 日差異文件
新增 noConflict,讓「Underscore」物件可以指派給其他變數。

0.1.02009 年 10 月 28 日文件
Underscore.js 初始版本。

A DocumentCloud Project