原文地址:https://dojotoolkit.org/documentation/tutorials/1.10/arrays/index.html
本翻譯項目放在GitBook上,歡迎參與。
GitBook地址:https://www.gitbook.com/book/limeng1900/dojo1-11-tutorials-translation-in-chinese/details
轉載請註明出處:http://blog.csdn.net/taijiedi13/ – 碎夢道
在本教程中,你將瞭解Dojo針對JavaScript數組的跨平臺解決方案:dojo/_base/array
。
入門
數據存取和操作是你的web應用開發時非常重要的部分。JavaScript的實現者們瞭解這些,所以爲了更加易用,他們在數組實例上加入了一些方法。可惜,不是所有的瀏覽器和環境都採取這些新方法。好消息是Dojo爲這些數組新方法提供輔助方法,因此無論你在什麼環境下運行,你都可以輕易駕馭數組。
查找
你在用數組的時候會需要的一項操作是找到數組的某一項。Dojo在dojo/_base/array
資源裏提供兩個函數:indexOf
和 lastIndexOf
。indexOf
方法從數組的最小索引查找到最大索引,lastIndexOf
則從大到小。它們接收同樣的參數:查找的數組、查找的項、開始查找的索引(可選)。來看一些例子:
require(["dojo/_base/array"], function(arrayUtil) {
var arr1 = [1,2,3,4,3,2,1,2,3,4,3,2,1];
arrayUtil.indexOf(arr1, 2); // returns 1
arrayUtil.indexOf(arr1, 2, 2); // returns 5
arrayUtil.lastIndexOf(arr1, 2); // returns 11
});
如果沒找到該項,兩個函數都返回-1。需要注意的是,兩個函數都使用嚴格比較(===),所以你能找到的不僅僅是原始值:
var obj1 = { id: 1 },
arr2 = [{ id: 0 }, obj1, { id: 2 }, { id: 3 }];
// This search returns 1, as obj1 is the second item
// in the array.
arrayUtil.indexOf(arr2, obj1);
// This search returns -1. While the objects may look similar,
// they are entirely different objects, and so this object
// isn't found in the array.
arrayUtil.indexOf(arr2, { id: 1 });
循環
另一個常用操作是循環遍歷數組的每一項。通常,會類似下面這樣:
var item;
for(var i = 0; i < arr.length; i++){
item = arr[i];
// do something with item
}
上面這樣做的缺點是當你在一個事件處理器裏訪問item
時,它可能不是你想要的項,而是所有事件處理器數組的最後一項。forEach
給了我們一個設置循環的標準方式,同時在作用域鏈查找期間也會保留項目。Array.prototype.forEach有兩個異常:
- 如果你的索引之中存在未定義的索引,它也會進行迭代。就是說如果你的數組裏有一個undefined值,它依然會對那個索引執行你的函數,而不能跳過它。
- 循環是執行在數組本身的。而當在支持的瀏覽器裏使用原生
forEach
方法時,它會遍歷數組的一個副本而不是數組本身。你在函數裏對原始數組做的任何改變在隨後的函數執行的都能看到。
實際上,這兩點差異適用於本教程中討論的所有方法。我們來看一個例子:
var arr = ["one", "two", "three", "four"],
// dom is from dojo/dom
list1 = dom.byId("list1");
// Skip over index 4, leaving it undefined
arr[5] = "six";
arrayUtil.forEach(arr, function(item, index){
// This function is called for every item in the array
if(index == 3){
// this changes the original array,
// which changes the item passed to
// the sixth invocation of this function
arr[5] = "seven";
}
// domConstruct is available at dojo/dom-construct
domConstruct.create("li", {
innerHTML: item + " (" + index + ")"
}, list1);
});
arrayUtil.forEach
方法接收三個參數:一個用來迭代的數組、一個爲數組每一項(包含已定義之間存在的未定義索引)調用的函數(或者回調)、一個對象(可選)用作調用回調的作用域。
你提供的回調將調用給數組的每一個索引直到最後分配的索引(包含在內),它接收三個參數:當前索引的對象或值、當前索引本身、要遍歷的數組的引用。回調也將在arrayUtil.forEach
第三個參數的作用域裏調用,如果沒提供第三個參數則爲全局對象(瀏覽器下爲window
)。來看下作用域參數:
var list2 = dom.byId("list2"),
myObject = {
prefix: "ITEM: ",
formatItem: function(item, index){
return this.prefix + item + " (" + index + ")";
},
outputItems: function(arr, node){
arrayUtil.forEach(arr, function(item, index){
domConstruct.create("li", {
innerHTML: this.formatItem(item, index)
}, node);
}, this);
}
};
myObject.outputItems(arr, list2);
這可能是作用域參數最常用的模式:傳遞this
以便於回調函數將在調用它的方法的作用域裏調用。當你使用widget時,這個模式非常有用,建議保存起來以備後用。
操作
Dojo讓循環變的很簡單,不過你就會經常想要獲得一個數組的數據,然後用它來做一些事再得到一個新數組。比如我們有一個字符串數組,想要將轉換成對象,並將對象的“name”屬性設爲字符串的值。我們可能這麼做:
var original = ["one", "two", "three", "four", "five"],
transformed = [];
arrayUtil.forEach(original, function(item, index){
transformed.push({
id: index * 100,
text: item
});
}); // [ { id: 0, text: "one" }, { id: 100, text: "two" }, ... ]
這沒什麼錯誤,不過新版的JavaScript和Dojo有一個相當的功能:arrayUtil.map
。我們來看看:
var mapped = arrayUtil.map(original, function(item, index){
return {
id: index * 100,
text: item
};
}); // [ { id: 0, text: "one" }, { id: 100, text: "two" }, ... ]
map
的參數和forEach
一樣。不同點在於返回值會被存儲在一個新數組裏,它的索引和原始數組一樣。從map
返回了新的數組。
Dojo覆蓋新版JavaScript的另一個常見轉換是filter
。filter
的想法是你有一個數組指向選擇其中一些符合條件的項。用forEach
也可以實現,不過filter
更簡單。
參數相比map
還是沒有改變,不過在filter
裏,會評估回調返回的值,如果爲真則將該項附加到filter
返回的數組裏。讓我們看另一個例子:
var filtered = arrayUtil.filter(mapped, function(item, index){
return item.id > 50 && item.id < 350;
}); // [ { id: 100, text: "two" }, { id: 200, text: "three" },
// { id: 300, text: "four" } ]
匹配
有時候你想知道一個數組的項是否能匹配一定的條件:或許你想知道一些對象是否有一個error屬性,或者你想確認所有的對象有一個text屬性。這就是some
和every
的用處了。它們的函數簽名很像filter
(包括回調的返回),不過不是返回一個數組,而是一個布爾值:如果數組每一項的回調都返回true
則every
返回true
,如果數組至少有一項的回調返回true
則some
返回true
。下面的例子應該能解釋地更清楚:
var arr1 = [1,2,3,4,5],
arr2 = [1,1,1,1,1];
arrayUtil.every(arr1, function(item){ return item == 1; }); // returns false
arrayUtil.some(arr1, function(item){ return item == 1; }); // returns true
arrayUtil.every(arr2, function(item){ return item == 1; }); // returns true
arrayUtil.some(arr2, function(item){ return item == 1; }); // returns true
arrayUtil.every(arr2, function(item){ return item == 2; }); // returns false
arrayUtil.some(arr2, function(item){ return item == 2; }); // returns false
簡單的理解就是every
就像是在if
聲明裏用的&&
,som
就像是||
。
小結
JavaScript規範已經提供了一些強大的數組方法,但不是所有的瀏覽器和環境都支持。Dojo的dojo/_base/array
模塊在數組的新舊方法之間搭起橋樑,讓你可以用更少的代碼更快、更高效的做更多的事。