你已經知道,集合表示一組互不相同的元素(不重複的元素)。在字典中,存儲的是[鍵,值]對,其中鍵名是用來查詢特定元素的。字典和集合很相似,集合以[值,值]的形式存儲元素,字典則是以[鍵,值]的形式來存儲元素。字典也稱作映射。
在本章中,我們會介紹幾個在現實問題上使用字典數據結構的例子:一個實際的字典(單詞和它們的釋義)以及一個地址簿。
7.1.1 創建字典
與Set
類相似,ECMAScript 6同樣包含了一個Map
類的實現,即我們所說的字典。
我們在本章中將要實現的類就是以ECMAScript 6中Map
類的實現為基礎的。你會發現它和Set
類很相似(但不同於存儲[值,值]對的形式,我們將要存儲的是[鍵,值]對)。
這是我們的Dictionary
類的骨架:
function Dictionary {
var items = {};
}
與Set
類類似,我們將在一個Object
的實例而不是數組中存儲元素。
然後,我們需要聲明一些映射/字典所能使用的方法。
set(key,value)
:向字典中添加新元素。delete(key)
:通過使用鍵值來從字典中移除鍵值對應的數據值。has(key)
:如果某個鍵值存在於這個字典中,則返回true
,反之則返回false
。get(key)
:通過鍵值查找特定的數值並返回。clear
:將這個字典中的所有元素全部刪除。size
:返回字典所包含元素的數量。與數組的length
屬性類似。keys
:將字典所包含的所有鍵名以數組形式返回。values
:將字典所包含的所有數值以數組形式返回。has
和set
方法我們首先來實現
has(key)
方法。之所以要先實現這個方法,是因為它會被set
和remove
等其他方法調用。我們可以通過如下代碼來實現:this.has = function(key) { return key in items; };
這個方法的實現和我們之前在
Set
類中的實現是一樣的。我們使用JavaScript中的in
操作符來驗證一個key
是否是items
對象的一個屬性。然後是
set
方法的實現:this.set = function(key, value) { items[key] = value; //{1} };
該方法接受一個
key
和一個value
作為參數。我們直接將value
設為items
對象的key
屬性的值。它可以用來給字典添加一個新的值,或者用來更新一個已有的值。delete
方法接下來,我們實現
delete
方法。它和Set
類中的delete
方法很相似,唯一的不同點在於我們將先搜索key
(而不是value
):this.delete= function(key) { if (this.has(key)) { delete items[key]; return true; } return false; };
然後我們可以使用JavaScript的
remove
操作符來從items
對像中移除key
屬性。get
和values
方法如果我們想在字典中查找一個特定的項,並檢索它的值,可以使用下面的方法:
this.get = function(key) { return this.has(key) ? items[key] : undefined; };
get
方法首先會驗證我們想要檢索的值是否存在(通過查找key
值),如果存在,將返回該值,反之將返回一個undefined
值(請記住undefined
值和null
值是不一樣的,第1章中提到過這個概念)。下一個是
values
方法。這個方法以數組的形式返回字典中所有values
實例的值:this.values = function { var values = ; for (var k in items) { //{1} if (this.has(k)) { values.push(items[k]); //{2} } } return values; };
首先,我們遍歷
items
對象的所有屬性值(行{1}
)。為了確定值存在,我們使用has
函數來驗證key
確實存在,然後將它的值加入values
數組(行{2}
)。最後,我們就能返回所有找到的值。我們不能僅僅使用
for-in
語句來遍歷items
對象的所有屬性,還需要使用hasOwnProperty
方法(驗證items
對象是否包含某個屬性),因為對象的原型也會包含對象的其他屬性(JavaScript基本的Object
類中的屬性將會被繼承,並存在於當前對像中,而對於這個數據結構來說,我們並不需要它們)。clear
、size
、keys
和getItems
方法clear
和size
方法與第6章Set
類中對應的方法是完全一樣的,因此我們就不在本章討論了。keys
方法返回在Dictionary
類中所有用於標識值的鍵名。要取出一個JavaScript對像中所有的鍵名,可以把這個對象作為參數傳入Object
類的keys
方法(到目前為止,書中創建的類,包括Dictionary
在內,都是JavaScript對像),如下:this.keys = function { return Object.keys(items); };
最後,我們來驗證
items
屬性的輸出值。我們可以實現一個返回items
變量的方法,叫作getItems
:this.getItems = function { return items; }
7.1.2 使用Dictionary
類
首先,我們來創建一個Dictionary
類的實例,然後給它添加三條電子郵件地址。我們將會使用這個dictionary
實例來實現一個電子郵件地址簿。
使用我們創建的類來執行如下代碼:
var dictionary = new Dictionary;
dictionary.set(\'Gandalf\', \'[email protected]\');
dictionary.set(\'John\', \'[email protected]\');
dictionary.set(\'Tyrion\', \'[email protected]\');
如果執行了如下代碼,輸出結果將會是true
:
console.log(dictionary.has(\'Gandalf\'));
下面的代碼將會輸出3
,因為我們向字典實例中添加了三個元素:
console.log(dictionary.size);
現在,執行下面的幾行代碼:
console.log(dictionary.keys);
console.log(dictionary.values);
console.log(dictionary.get(\'Tyrion\'));
輸出結果分別如下所示:
[\"Gandalf\", \"John\", \"Tyrion\"]
[\"[email protected]\", \"[email protected]\", \"[email protected]\"]
[email protected]
最後,再執行幾行代碼:
dictionary.delete(\'John\');
再執行下面的代碼:
console.log(dictionary.keys);
console.log(dictionary.values);
console.log(dictionary.getItems);
輸出結果如下所示:
[\"Gandalf\", \"Tyrion\"]
[\"[email protected]\", \"[email protected]\"]
Object {Gandalf: \"[email protected]\", Tyrion:
\"[email protected]\"}
移除了一個元素後,現在的dictionary
實例中只包含兩個元素了。加粗的一行表現了items
對象的內部結構。