最近一直在看es6新曾的一寫數(shù)組的拓展,總結(jié)出了一些知識點
- find,findIndex事示,inclueds
- Map Set
- 靜態(tài)方法(from早像,of)
find,findIndex,inclueds
find和findIndex
語法
arr .find(callback(element[, index[, array]])[, thisArg])
arr .findIndex(callback(element[, index[, array]])[, thisArg])參數(shù)
callback
函數(shù)對數(shù)組中的每個值執(zhí)行,取三個參數(shù)
element
當前元素在數(shù)組中處理很魂。
index(可選的)
數(shù)組中正在處理的當前元素的索引扎酷。
array(可選的)
該陣列find被召喚檐涝。
thisArg (可選的)
this在執(zhí)行時使用的對象callback遏匆。
數(shù)組實例的find方法,用于找出第一個符合條件的數(shù)組成員谁榜。它的參數(shù)是一個回調(diào)函數(shù)幅聘,所有數(shù)組成員依次執(zhí)行該回調(diào)函數(shù),直到找出第一個返回值為true的成員窃植,然后返回該成員的value帝蒿。如果沒有符合條件的成員,則返回undefined巷怜。
let inventory = [
{name: 'apples', quantity: 2},
{name: 'bananas', quantity: 0},
{name: 'cherries', quantity: 5}
];
function findCherries(fruit) {
return fruit.name === 'cherries';
}
console.log(inventory.find(findCherries)); // { name: 'cherries', quantity: 5 }
下面代碼是找出數(shù)組中第一個大于9的成員
[1, 5, 10, 15].find((value, index, arr)=> {
return value > 9;
}) // 10
[1, 5, 10, 15].find((value, index, arr)=> {
if(index>2){
return value > 9;
}
}) // 15
數(shù)組實例的findIndex方法的用法與find方法非常類似葛超,返回第一個符合條件的數(shù)組成員的位置暴氏,如果所有成員都不符合條件,則返回-1绣张。上面find一樣答渔,不贅述。
[1, 5, 10, 15].findIndex(function(value, index, arr) {
return value > 9;
}) // 2
這兩個方法都可以接受第二個參數(shù)侥涵,用來綁定回調(diào)函數(shù)的this對象沼撕。
function f(value){
return value > this.age;
}
let person = {name: 'John', age: 20};
[10, 12, 26, 15].find(f, person); // 26
includes
includes方法返回一個布爾值,表示某個數(shù)組是否包含給定的值芜飘,與字符串的includes方法類似
語法
arr .includes(searchElement [务豺,fromIndex])
參數(shù)
searchElement
要在數(shù)組中定位的元素。
fromIndex (可選的)
用于開始搜索的索引嗦明。如果索引大于或等于數(shù)組的長度笼沥,則返回-1,這意味著不會搜索該數(shù)組招狸。如果提供的索引值為負數(shù)敬拓,則將其作為數(shù)組末尾的偏移量。注意:如果提供的索引為負數(shù)裙戏,則仍會從前到后搜索數(shù)組乘凸。如果提供的索引為0,則將搜索整個數(shù)組累榜。默認值:0(搜索整個數(shù)組)营勤。
返回值
數(shù)組中元素的第一個索引; -1如果沒有找到。
[1, 2, 3].includes(2) // true
[1, 2, 3].includes(4) // false
[1, 2, NaN].includes(NaN) // true
[1, 2, 3].includes(3, 3); // false
[1, 2, 3].includes(3, -1); // true
沒有該方法之前壹罚,我們通常使用數(shù)組的indexOf方法葛作,檢查是否包含某個值。
indexOf方法有兩個缺點猖凛,一是不夠語義化赂蠢,它的含義是找到參數(shù)值的第一個出現(xiàn)位置,所以要去比較是否不等于-1辨泳,表達起來不夠直觀虱岂。二是,它內(nèi)部使用嚴格相等運算符(===)進行判斷菠红,這會導致對NaN的誤判第岖。
includes使用的是不一樣的判斷算法,就沒有這個問題试溯。
[NaN].indexOf(NaN)
// -1
[NaN].includes(NaN)
// true
另外蔑滓,這find(),findIndex()兩個方法都可以發(fā)現(xiàn)NaN,也彌補了數(shù)組的indexOf方法的不足。
[NaN].findIndex(y => Object.is(NaN, y))
// 0
[NaN].find(y => Object.is(NaN, y))
// NaN
附: Object.is() , === 和 == 對比表
//Object.is()的實現(xiàn)原理
isObject = function(x, y) {
if (x === y) { // Steps 1-5, 7-10
// 針對 +0不等于-0
return x !== 0 || 1 / x === 1 / y;
} else {
// 針對 NaN等于NaN
return x !== x && y !== y;
}
};
數(shù)組的去重
//最原始方法
var array = [1, 1, '1', '1'];
function unique(array) {
// res用來存儲結(jié)果
var res = [];
for (var i = 0, arrayLen = array.length; i < arrayLen; i++) {
for (var j = 0, resLen = res.length; j < resLen; j++ ) {
if (array[i] === res[j]) {
break;
}
}
// 如果array[i]是唯一的键袱,那么執(zhí)行完循環(huán)燎窘,j等于resLen
if (j === resLen) {
res.push(array[i])
}
}
return res;
}
console.log(unique(array)); // [1, "1"]
//indexOf
var array = [1, 1, '1'];
function unique(array) {
var res = [];
for (var i = 0, len = array.length; i < len; i++) {
var current = array[i];
if (res.indexOf(current) === -1) {
res.push(current)
}
}
return res;
}
console.log(unique(array));
//filter
var array = [1, 2, 1, 1, '1'];
function unique(array) {
var res = array.filter(function(item, index, array){
return array.indexOf(item) === index;
})
return res;
}
console.log(unique(array));
Map和Set
在以數(shù)組和對象為編程主力的JavaScript 語言,ES6 中引入了4種新的數(shù)據(jù)結(jié)構(gòu)蹄咖,分別是:集合(Set)荠耽、弱集合(WeakSet)、映射(Map)比藻、弱映射(WeakMap)铝量。
Set
Set 對象是值的集合,可以按照插入的順序迭代它的元素银亲。Set 中的元素只會出現(xiàn)一次慢叨,即 Set 中的元素是唯一的。
語法
new Set([ iterable ]);
參數(shù)
iterable
是一個可迭代的對象务蝠,它的所有元素將被添加到新的 Set 中拍谐。
由于 Set 中的值總是唯一的,所以需要判斷兩個值是否相等馏段。在上面轩拨,內(nèi)部使用Object.is()方法檢測兩個值是否一致,但+0院喜、-0和0被視為是相等的元素亡蓉,NaN 和 undefined 是可以被存儲在 Set 中的,因為 NaN 在ES6中是嚴格相等的喷舀。
new Set([NaN, NaN, 2, "2", +0, -0]); // Set(4) {NaN, 2, '2', 0}
屬性
Set.prototype.size:返回 Set 對象的值的個數(shù)砍濒。
let mySet1 = new Set([NaN, NaN, 2, 3, 5, 5]);
mySet1.size; // 4
方法
(1)、在 Set 對象尾部添加一個元素:Set.prototype.add(value)
let mySet1=new Set([NaN,1,2,3]).add(NaN).add(2).add(4); //Set(5) {NaN, 1, 2, 3, 4}
(2)硫麻、清除 Set 中所有的元素:Set.prototype.clear()
let mySet2=new Set(NaN,1,2,3).clear(); //undefined
(3)爸邢、判斷值是否存在于 Set 中:Set.prototype.has(value);
let mySet3=new Set([1,2,3,4,5]).has(2); //true
let mySet4=new Set([1,2,3,4,5]).has(7); //false
(4)拿愧、刪除 Set 中的某個值: Set.prototype.delete(value);
var mySet = new Set();
mySet.add("foo");
mySet.delete("bar"); // 返回 false杠河,不包含 "bar" 這個元素
mySet.delete("foo"); // 返回 true,刪除成功
mySet.has("foo"); // 返回 false浇辜,"bar" 已經(jīng)成功刪除
WeakSet
1券敌、WeakSet 結(jié)構(gòu)與 Set 結(jié)構(gòu)類似,WeakSet 是一個構(gòu)造函數(shù)奢赂,可以使用 new 命令創(chuàng)建 WeakSet 數(shù)據(jù)結(jié)構(gòu)陪白。
const a= ["yuan", "monkey"];
const myWeakSet = new WeakSet(a); // WeakSet {"yuan", "monkey" }
2颈走、與 Set 區(qū)別
(1)膳灶、WeakSet 的成員只能是對象,而不能是其他類型的值。
(2)轧钓、WeakSet 中的對象都是弱引用序厉,即垃圾回收機制不考慮 WeakSet 對該對象的引用。 也就是說毕箍,如果其他對象都不再引用該對象弛房,那么垃圾回收機制會自動回收該對象所占用的內(nèi)存,不考慮該對象還存在于 WeakSet 之中而柑。這是因為垃圾回收機制依賴引用計數(shù)文捶,如果一個值的引用次數(shù)不為0,垃圾回收機制就不會釋放這塊內(nèi)存媒咳。結(jié)束使用該值之后粹排,有時會忘記取消引用,導致內(nèi)存無法釋放涩澡,進而可能會引發(fā)內(nèi)存泄漏顽耳。WeakSet 里面的引用,都不計入垃圾回收機制妙同,所以就不存在這個問題射富。因此,WeakSet 適合臨時存放一組對象粥帚,以及存放跟對象綁定的信息胰耗。只要這些對象在外部消失,它在 WeakSet 里面的引用就會自動消失芒涡。
由于上面這個特點宪郊,WeakSet 的成員是不適合引用的,因為它會隨時消失拖陆。另外弛槐,由于 WeakSet 內(nèi)部有多少個成員,取決于垃圾回收機制有沒有運行依啰,運行前后很可能成員個數(shù)是不一樣的乎串,而垃圾回收機制何時運行是不可預測的,因此 ES6 規(guī)定 WeakSet 不可遍歷速警。
這些特點同樣適用于本章后面要介紹的 WeakMap 結(jié)構(gòu)叹誉。
(3)、WeakSet 沒有size 屬性闷旧,沒有辦法遍歷其成員长豁。
3、方法
(1)忙灼、WeakSet.prototype.add(value):添加新成員匠襟;
(2)钝侠、WeakSet.prototype.delete(value):清楚指定成員;
(3)酸舍、WeakSet.prototype.has(value):判斷是否存在某個成員
Map
Map 對象保存鍵值對帅韧。任何值(對象或者原始值) 都可以作為一個鍵或一個值。
一個Map對象以插入順序迭代其元素 — 一個 for...of 循環(huán)為每次迭代返回一個[key啃勉,value]數(shù)組忽舟。
語法
new Map([ iterable ]);
參數(shù)
iterable
Iterable 可以是一個數(shù)組或者其他 iterable 對象,其元素或為鍵值對淮阐,或為兩個元素的數(shù)組叮阅。 每個鍵值對都會添加到新的 Map。null
會被當做undefined泣特。
方法
(1)Map.prototype.set(key, value)
設(shè)置Map對象中鍵的值帘饶。返回該Map對象。
(2)Map.prototype.clear()
移除Map對象的所有鍵/值對 群扶。
(3)Map.prototype.has(key)
返回一個布爾值及刻,表示Map實例是否包含鍵對應(yīng)的值崇堰。
myMap.set("bar", "baz");
myMap.set(1, "foo");
myMap.size; // 2
myMap.has("bar"); // true
myMap.clear();
myMap.size; // 0
myMap.has("bar") // false
(4)Map.prototype.delete(key)
移除任何與鍵相關(guān)聯(lián)的值徙融,并且返回該值容诬,該值在之前會被
var myMap = new Map();
myMap.set("bar", "foo");
myMap.delete("bar"); // 返回 true笤昨。成功地移除元素
myMap.has("bar"); // 返回 false涯保。"bar" 元素將不再存在于 Map 實例中
應(yīng)用
應(yīng)用
(1)旧困、Map 與 數(shù)組之間的相互轉(zhuǎn)換
// Map 轉(zhuǎn)數(shù)組
var myMap = new Map();
myMap.set("bar", "foo");
myMap.set(1, "bar");
[...myMap]; // [ ["bar", "foo"], [1, "bar"] ]
// 數(shù)組轉(zhuǎn)Map
const arr = new Map( [ ["bar", "foo"], [1, "bar"] ]);
console.log(arr); // Map {"bar" => "foo", 1 => "bar"}
(2)寨蹋、Map 與對象相互轉(zhuǎn)換
// Map 轉(zhuǎn)對象
function strMapToObj(strMap) {
let obj = Object.create(null);
for (let [k, v] of strMap) {
obj[k] = v;
}
return obj;
}
const myMap = new Map();
myMap.set("bar", "foo")
.set(1, "ooo");
strMapToObj(myMap ); // Object {1: "ooo", bar: "foo"}
// 對象轉(zhuǎn) Map
function objToStrMap(obj) {
let strMap = new Map();
for (let k of Object.keys(obj)) {
strMap.set(k, obj[k]);
}
return strMap;
}
objToStrMap({1: "ooo", bar: "foo"}); // Map {"1" => "ooo", "bar" => "foo"}
(3)蹄胰、Map 與 JSON 相互轉(zhuǎn)換
// Map 轉(zhuǎn) JSON
// Map 的鍵名為字符串
function strMapToJson(jsonStr) {
return JSON.stringify(strMapToObj(jsonStr));
}
const myMap = new Map();
myMap.set("bar", "foo")
.set(1, "ooo");
strMapToJson(myMap); // "{"1":"ooo","bar":"foo"}"
// Map 的鍵名為非字符串
function mapToArrayJson(map) {
return JSON.stringify([...map]);
}
mapToArrayJson(myMap); // "[["bar","foo"],[1,"ooo"]]"
// Json 轉(zhuǎn) Map
// 正常情況下所有鍵名都為字符串
function jsonToStrMap(jsonStr) {
return objToStrMap(JSON.parse(jsonStr));
}
jsonToStrMap("{"1":"ooo","bar":"foo"}"); // Map {"1" => "ooo", "bar" => "foo"}
// 整個JSON 是數(shù)組
function jsonToMap(jsronStr) {
return new Map(JSON.parse(jsronStr));
}
jsonToMap([["bar","foo"],[1,"ooo"]]); // Map {"1" => "ooo", "bar" => "foo"}
WeakMap
含義
WeakMap 結(jié)構(gòu)與 Map結(jié)構(gòu)類似幕垦,也是用于生成鍵值對的集合丢氢。
與 Map 區(qū)別
(1)WeakMap 只接受對象作為鍵名(null 除外),不接受其他類型的值作為鍵名先改。
(2)WeakMap 的鍵名所指向的對象不計入垃圾回收機制疚察。
(3)沒有keys()、values()仇奶、entries() 遍歷操作貌嫡。
(4)沒有size 屬性。
(5)不支持clear() 方法该溯。
WeakMap 應(yīng)用的典型場合就是 DOM 節(jié)點作為鍵名岛抄。下面是一個例子。
let myElement = document.getElementById('logo');
let myWeakmap = new WeakMap();
myWeakmap.set(myElement, {timesClicked: 0});
myElement.addEventListener('click', function() {
let logoData = myWeakmap.get(myElement);
logoData.timesClicked++;
}, false);
上面代碼中狈茉,myElement是一個 DOM 節(jié)點夫椭,每當發(fā)生click事件,就更新一下狀態(tài)氯庆。我們將這個狀態(tài)作為鍵值放在 WeakMap 里蹭秋,對應(yīng)的鍵名就是myElement扰付。一旦這個 DOM 節(jié)點刪除,該狀態(tài)就會自動消失感凤,不存在內(nèi)存泄漏風險。
靜態(tài)方法(from粒督,of)
Array.from方法用于將兩類對象轉(zhuǎn)為真正的數(shù)組:類似數(shù)組的對象(array-like object)和可遍歷(iterable)的對象(包括 ES6 新增的數(shù)據(jù)結(jié)構(gòu) Set 和 Map)陪竿。
let arrayLike = {
'0': 'a',
'1': 'b',
'2': 'c',
length: 3
};
// ES5的寫法
var arr1 = [].slice.call(arrayLike); // ['a', 'b', 'c']
// ES6的寫法
let arr2 = Array.from(arrayLike); // ['a', 'b', 'c']
//Set
let newArray=new Set(['a','b','c'])
let arr3=Array.from(newArray) //['a','b','c']
Array.to方法是用于將一組值,轉(zhuǎn)換為數(shù)組屠橄。和Array()的用途相似,但是這個方法的主要目的族跛,是彌補數(shù)組構(gòu)造函數(shù)Array()的不足。因為參數(shù)個數(shù)的不同锐墙,會導致Array()的行為有差異礁哄。
Array() // []
Array(3) // [, , ,]
Array(3, 11, 8) // [3, 11, 8]
Array.of() // []
Array.of(1) // [1]
Array.of(3,11,8) // [1, 2]
上面代碼中,Array方法沒有參數(shù)溪北、一個參數(shù)桐绒、三個參數(shù)時,返回結(jié)果都不一樣之拨。只有當參數(shù)個數(shù)不少于 2 個時茉继,Array()才會返回由參數(shù)組成的新數(shù)組。參數(shù)個數(shù)只有一個時蚀乔,實際上是指定數(shù)組的長度烁竭。
Array.of基本上可以用來替代Array()或new Array(),并且不存在由于參數(shù)不同而導致的重載吉挣。它的行為非常統(tǒng)一派撕。Array.of總是返回參數(shù)值組成的數(shù)組。如果沒有參數(shù)睬魂,就返回一個空數(shù)組终吼。
數(shù)組的空值
數(shù)組的空位指,數(shù)組的某一個位置沒有任何值氯哮。比如衔峰,Array構(gòu)造函數(shù)返回的數(shù)組都是空位。注意蛙粘,空位不是undefined垫卤,一個位置的值等于undefined,依然是有值的出牧⊙ㄖ猓空位是沒有任何值
ES5 對空位的處理,已經(jīng)很不一致了舔痕,大多數(shù)情況下會忽略空位评抚。
forEach(), filter(), reduce(), every() 和some()都會跳過空位豹缀。
map()會跳過空位,但會保留這個值
join()和toString()會將空位視為undefined慨代,而undefined和null會被處理成空字符串邢笙。
// forEach方法
[,'a'].forEach((x,i) => console.log(i)); // 1
// filter方法
['a',,'b'].filter(x => true) // ['a','b']
// every方法
[,'a'].every(x => x==='a') // true
// reduce方法
[1,,2].reduce((x,y) => x+y) // 3
// some方法
[,'a'].some(x => x !== 'a') // false
// map方法
[,'a'].map(x => 1) // [,1]
// join方法
[,'a',undefined,null].join('#') // "#a##"
// toString方法
[,'a',undefined,null].toString() // ",a,,"
ES6中則是明確的將空處理成了undefined,由于空位的處理規(guī)則非常不統(tǒng)一,所以建議避免出現(xiàn)空位侍匙。
Array.from方法會將數(shù)組的空位氮惯,轉(zhuǎn)為undefined,也就是說想暗,這個方法不會忽略空位妇汗。
Array.from(['a',,'b'])
// [ "a", undefined, "b" ]
擴展運算符(...)也會將空位轉(zhuǎn)為undefined。
[...['a',,'b']]
// [ "a", undefined, "b" ]
copyWithin()會連空位一起拷貝说莫。
[,'a','b',,].copyWithin(2,0) // [,"a",,"a"]
fill()會將空位視為正常的數(shù)組位置杨箭。
new Array(3).fill('a') // ["a","a","a"]
for...of循環(huán)也會遍歷空位。
let arr = [, ,];
for (let i of arr) {
console.log(1);
}
// 1
// 1
問題 :
1.不太了解靜態(tài)方法和實例方法的區(qū)別
2.對promise概念有點模糊储狭,async 的使用