javascript學習筆記(3)--map&set&元素遍歷&filter

JavaScript的默認對象表示方式{}可以視爲其他語言中的Map或Dictionary的數據結構,即一組鍵值對
但是JavaScript的對象有個小問題,就是鍵必須是字符串。但實際上Number或者其他數據類型作爲鍵也是非常合理的。 爲了解決這個問題,ES6規範引入了新的數據類型Map

var m = new Map([['Michael', 95], ['Bob', 75], ['Tracy', 85]]); //這是個object對象
m.get('Michael'); // 95 
var m = new Map(); // 空Map 
m.set('Adam', 67); // 添加新的key-value 
m.set('Bob', 59); 
m.has('Adam'); // 是否存在key 'Adam': true 
m.get('Adam'); // 67 
m.delete('Adam'); // 刪除key 'Adam' 
m.get('Adam'); // undefined 不存在

由於一個key只能對應一個value,所以,多次對一個key放入value,會把值更新爲後面的值

var m = new Map(); 
m.set('Adam', 67); 
m.set('Adam', 88); 
m.get('Adam'); //88

Set和Map類似,也是一組key的集合,但不存儲value,由於key不能重複,所以,在Set中,沒有重複的值,重複元素在Set中自動被過濾
要創建一個Set,需要提供一個Array作爲輸入,或者直接創建一個空Set:

var s1 = new Set(); // 空Set 
var s2 = new Set([1, 2, 3]); // 含1, 2, 3 
var s = new Set([1, 2, 3, 3, '3']); 
s; // Set {1, 2, 3, "3"}"3"和3不同

通過add(key)方法可以添加元素到Set中,可以重複添加,但不會有效果

 s.add(4) 
 s ;//{1, 2, 3, 4} 
s.add(4) 
 s ;//{1, 2, 3, 4} 

通過delete(key)方法可以刪除元素:

var s = new Set([1, 2, 3]); 
s; // Set {1, 2, 3} 
s.delete(3); 
s; // Set {1, 2} 

控制檯返回錯誤信息Error:Not a number

throw 'Not a number'; //Error:Not a number

遍歷Array可以採用下標循環,遍歷Map和Set就無法使用下標
爲了統一集合類型,ES6標準引入了新的iterable類型,Array、Map和Set都屬於iterable類型
具有iterable類型的集合可以通過新的for … of循環來遍歷
用for … of循環遍歷集合,用法如下

var a = ['A', 'B', 'C']; 
var s = new Set(['A', 'B', 'C']); 
var m = new Map([[1, 'x'], [2, 'y'], [3, 'z']]); 

for (var x of a)
 {  console.log(x); };//A B C

for (var x of s) {console.log(x); };//A B C

for (var x of m) {console.log(x[0] + '=' + x[1]); };//1=x 2=y3=z

注意Map遍歷的時候,每一個Map的元素相當於是個數組,一個是Key,一個是Value,對應着x[0]和x[1]

for … of循環和for … in循環有何區別?
for … in循環由於歷史遺留問題,它遍歷的實際上是對象的屬性名稱(key)
一個Array數組實際上也是一個對象,它的每個元素的索引被視爲一個屬性,當我們手動給Array對象添加了額外的屬性後,for … in循環將帶來意想不到的意外效果

var a = ['A', 'B', 'C'];
a.name="hello";
for (var x in a) { console.log(x); }0 1 2 name
for (var x in a) { console.log(a[x]); };//AB C hello

for … in循環將把name包括在內,但Array的length屬性卻不包括在內,所以如果用for…in循環可能會出現問題

for … of循環則完全修復了這些問題,它只循環集合本身的元素

var a = ['A', 'B', 'C']; 
a.name = 'Hello'; 
for (var x of a) { console.log(x); };//A B C

更好的方式是直接使用iterable內置的forEach方法,它接收一個函數,每次迭代就自動回調該函數
以Array爲例 ,因爲組成array的是element(元素本身 ),index(索引),array(數組對象)
function()內的順序就是按着元素,索引,數組,傳入的變量名可以修改,(這裏只是方便大家理解)

var a = ['A', 'B', 'C']; 
a.forEach(function (element, index, array)
 { 
console.log(element);
}); 
A 
B 
C

a.forEach(function (element, index, array)
 { 
console.log(index);
});
0 
1 
2

a.forEach(function (element, index, array)
 { 
console.log(array);
});
Array(3) [ "A", "B", "C" ]
Array(3) [ "A", "B", "C" ]
Array(3) [ "A", "B", "C" ]

Set與Array類似,但Set沒有索引,因此回調函數的前兩個參數都是元素本身(element),同理這裏的變量名也只是方便大家理解,可以修改

 var s = new Set(['A', 'B', 'C']); 
 s.forEach(function (element, sameElement, set) { console.log(element); });

Map的回調函數參數依次爲value、key和map本身,同理變量名只是方便理解

 var m = new Map([[1, 'x'], [2, 'y'], [3, 'z']]); 
 m.forEach(function (value, key, map) { console.log(value); }); 

如果對某些參數不感興趣,由於JavaScript的函數調用不要求參數必須一致,因此可以忽略它們
只需要獲得Array的element

var a = ['A', 'B', 'C']; 
a.forEach(function (element) { console.log(element); })

filter也是一個常用的操作,它用於把Array的某些元素過濾掉,然後返回剩下的元素
和map()類似,Array的filter()也接收一個函數,和map()不同的是,filter()把傳入的函數依次作用於每個元素,然後根據返回值是true還是false決定保留還是丟棄該元素

例如,在一個Array中,刪掉偶數,只保留奇數

 var arr = [1, 2, 4, 5, 6, 9, 10, 15]; 
 var r = arr.filter(function (x) { return x % 2 !== 0; });
 r;//Array(4) [ 1, 5, 9, 15 ]
 arr;//Array(8) [ 1, 2, 4, 5, 6, 9, 10, 15 ] 

x&2!==0如果返回true說明是個奇數,如果是偶數則返回false
但注意了,arr不變

把Array中的空字符串刪掉
先講一下trim函數
trim用於去除字符串的頭尾空格

var  str="    Noob  ";
str.trim();//"Noob"

由於javascript裏面有幾個先天就是false的常量
null,undefined,’’,"",0
所以有時候如果出現在了array裏面我們可能想要去掉

var arr = ['A', '', 'B', null, undefined, 'C', ' ']; 
var r = arr.filter(function (s) { return s});
r;//Array(4) [ "A", "B", "C", " " ]第四個裏面有空格,所以不是非空 

另外上面出現的5個爲false的,具體還是有一些差別的

""==false;//true
!null;//true
null==false;//false
!undefined;//true
undefined==false;//false
''==false;//true
0==false;//true

‘’,"",0直接就==false,但是null,undefined並不等於false,因爲他們還有本身的意義,但是!後就等於true了,在一些返回值裏面還是可以認爲和false等價的,比如說像我們這裏,根據返回值true和false進行取捨,盲猜實現的原理裏面需要取個反,不然undefined和null還要出一點問題
這也提醒我們,之後如果判斷null和undeifned的時候還是需要取反

但有時候,我們只想去掉全都是空格和空字符串,null和undefiend或許還有點用

var arr = ['A', '', 'B', null, undefined, 'C', ' ']; 
var r = arr.filter(function (s) { return String(s).trim();  });
r;//Array(5) [ "A", "B", null, undefined, "C" ]

注意啦,這裏別用toString,因爲null和undefined沒有toString這個屬性

String(null);//"null"
String(undefined);//"undefined"

filter()接收的回調函數,其實可以有多個參數
通常我們僅使用第一個參數,表示Array的某個元素
回調函數還可以接收另外兩個參數,表示元素的位置和數組本身

var arr = ['A', 'B', 'C']; 
var r = arr.filter(function (element, index, self) { console.log(element); 
console.log(index); 
console.log(self); 
return true; }); 
A 
0 
Array(3) [ "A", "B", "C" ]
B 
1 
Array(3) [ "A", "B", "C" ]
C 
2 
Array(3) [ "A", "B", "C" ]

r
Array(3) [ "A", "B", "C" ]

按照每個元素的順序依次執行,arr也被重複輸出了3次
跟上面的ForEach有點像,不過後面要加上return,因爲filter的本職工作

利用filter,去除Array的重複元素
indexOf()再上一節剛剛講了,會搜索指定字符串或者字符出現的位置,返回第一個值

var arr = ['apple', 'strawberry', 'banana', 'pear', 'apple', 'orange', 'orange', 'strawberry']; 
var r = arr.filter(function (element, index, self) { return self.indexOf(element) === index; }); 

r
Array(5) [ "apple", "strawberry", "banana", "pear", "orange" ]

這裏的indexOf(element)只會返回第一個出現的索引,所以只有當元素是那個第一個出現的纔會被留下,後面重複出現的都會被過濾掉

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章