介紹jQuery map()與grep()
7 | 33,711 |
寫這篇的動機是常在專案看到「古典式」JavaScript陣列處理,例如:跑迴圈將物件陣列的某個字串屬取出轉成字串陣列、篩選物件陣列取得特定類別的集合。用for迴圈處理沒什麼不對,但既然專案已經用了jQuery,能一行搞定卻寫成三五行不免可惜(程式又不按行數計酬,寫愈多手愈酸咩 XD)。感覺上還有些朋友不認識$.map()跟$.grep()這兩個好東西,故寫篇文章推薦一下。
若用LINQ做比方,$.map()相當於 .Select(o => 傳回數值或其他型別物件).ToArray(),可將物件陣列轉換成某個屬性或其他型別物件組成的陣列;$.grep()則類似 .Where(o => 傳回布林值).ToArray(),可過濾陣列保留符合條件的元素項目。
使用概念如下,輸入陣列,執行後傳回陣列:
$.map(array, function(element, index) { return 新陣列的元素; });
(註:若輸出陣列想略過特定元素,就return null或undefined)
$.grep(array, function(element, index) { return true或false; });
(傳回true的元素才會出現在篩選結果)
來看實例,以下程式有四個範例,分別用傳統方法及$.map(), $.grep()實現「物件陣列轉字串陣列」以及「過濾物件陣列保留特定類別」,程式不複雜,直接看程式碼,開始想想可以用在哪些專案角萿吧!
線上展示
排版顯示純文字
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>jQuery map & grep</title>
</head>
<body>
<script src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
<script>
function Product(category, name) {
this.category = category;
this.name = name;
}
var items = [
new Product("Phone", "iPhone4S"),
new Product("Phone", "Lumia 920"),
new Product("Phone", "小米"),
new Product("Pad", "Nexus7"),
new Product("Pad", "iPad")
];
//範例一:取得產品名稱字串陣列
var names = [];
for (var i = 0; i < items.length; i++) {
names.push(items[i].name);
}
//同場加映:JSON.stringify時傳入額外參數加上縮排
alert(JSON.stringify(names, null, 4));
//範例二:篩選手機類的產品陣列
var phones = [];
$.each(items, function(i, item) {
if (item.category == "Phone")
phones.push(item);
});
alert(JSON.stringify(phones, null, 4));
//jQuery改良版
//範例三:取得產品名稱字串陣列$.map()
var names = $.map(items, function(item) {
return item.name;
});
alert(JSON.stringify(names, null, 4));
//範例四:篩選手機類的產品陣列$.grep()
var phones = $.grep(items, function(item) {
return item.category == "Phone";
});
alert(JSON.stringify(phones, null, 4));
</script>
</body>
</html>
Comments
# by HamielKuo
您好, 有看到文章內有用到[$.each(],我這邊有遇到下面的情況,目前是採用[for]來解決效能問題,想請問是否有其他解決方式? 情況: 專案用Kendo UI Grid,需在每次重整(如跳轉grid 分頁)時將Grid內的下拉選單內容改為Grid欄位對應的顯示,有採用[$.each(],但後來遇到效能問題,故回頭改成用[for]來解決,感覺是有快了些.
# by Phoenix
看起來好好用的東西,好後悔以前不認識他呀QQ
# by Cash
黑大.. 範例三 的變數名稱應該是 names
# by Billy
雖然有map, grep 等新方法,但是萬變不離其宗,若追求速度的話,沒有方法可以比單純的 for loop 更快的了,而且亦是永遠不會忘記、不算複雜的方法。 map, grep 從上述的程式碼看來,沒有比for loop 簡單多少。
# by Jeffrey
to HamielKuo, 我非常好奇使用$.each()效能不佳,改用for才克服的案例,依直覺應不致有如此大的差異,可否再多提供一些細節? to Cash, 謝謝指正。 to Billy, 同意。for 迴圈具備單純,不需學習的特性。是否採用可視個人偏好,但學會它就多一項選擇,有利無害,即便最後決定用for比較好,考量應是「比較喜歡for」而非「不知道有$.grep()/$.map()」,也算文章有達到它的效果。
# by Billy
同意,讓我多介紹一個function - reduce(),從左到右處理陣列元素,最後返回一個數值。 簡單的例子: var total = [0, 1, 2, 3].reduce(function(a, b) { return a + b; }); https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce Map + Reduce 是functional programming一個經典組合 https://en.wikipedia.org/wiki/MapReduce
# by Jeffrey
to Billy, reduce()用來累計或比max/min很好用,也是可替代for的好工具,已筆記,感謝分享。