摘要:如果數(shù)組已經(jīng)為空,則不改變數(shù)組,并返回值。中所有在數(shù)組被修改時(shí)都遵從這個(gè)原則,以下不再重復(fù)方法會給原數(shù)組中的每個(gè)元素都按順序調(diào)用一次函數(shù)。每次執(zhí)行后的返回值沒有指定返回值則返回組合起來
1 ES3中的數(shù)組方法數(shù)組應(yīng)該是我們在寫程序中應(yīng)用到最多的數(shù)據(jù)結(jié)構(gòu)了,相比于無序的對象,有序的數(shù)組幫我們在處理數(shù)據(jù)時(shí),實(shí)在是幫了太多的忙了。今天剛好看到一篇Array.include的文章,忽然發(fā)現(xiàn)經(jīng)過幾個(gè)ES3,ES5,ES6,ES7幾個(gè)版本的更迭,發(fā)現(xiàn)在代碼中用到了好多數(shù)組的方法,所以準(zhǔn)備全部列出來,也是給自己加深印象
ES3兼容現(xiàn)在所有主流瀏覽器
ES3中的方法毫無疑問大家已經(jīng)爛熟在心了,不過中間有些細(xì)節(jié)可以回顧加深一下記憶,比如是否修改原數(shù)組返回新數(shù)組,執(zhí)行方法之后的返回值是什么,某些參數(shù)的意義是否搞混等等。熟悉的的可以直接快速瀏覽或者跳過。
1.1 join()方法Array.join()方法是將一個(gè)數(shù)組里面的所有元素轉(zhuǎn)換成字符串,然后再將他們連接起來返回一個(gè)新數(shù)組??梢詡魅胍粋€(gè)可選的字符串來分隔結(jié)果字符串中的所有元素。如果沒有指定分隔字符串,就默認(rèn)使用逗號分隔。
let a = [1,2,3,4,5,6,7]; let b = a.join(); // b = "1,2,3,4,5,6,7"; let c = a.a.join(" "); // b = "1 2 3 4 5 6 7";
1.2 reverse()方法方法Array.join()恰好與String.split()相反,后者是通過將一個(gè)字符串分隔成幾個(gè)元素來創(chuàng)建數(shù)組
Array.reverse()方法將顛倒數(shù)組中元素的順序并返回一個(gè)顛倒后的數(shù)組。它在原數(shù)組上執(zhí)行這一操作,所以說并不是創(chuàng)建了一個(gè)新數(shù)組,而是在已存在的數(shù)組中對元素進(jìn)行重排。
let a = [1,2,3,4,5,6,7]; a.reverse(); // a = [7,6,5,4,3,2,1]1.3 sort()方法
Array.sort()是在原數(shù)組上進(jìn)行排序,返回排序后的數(shù)組。如果調(diào)用方法時(shí)不傳入?yún)?shù),那么它將按照字母順序?qū)?shù)組元素進(jìn)行排序,說得更精確點(diǎn),是按照字符編碼的順序進(jìn)行排序。要實(shí)現(xiàn)這一點(diǎn),首先應(yīng)把數(shù)組的元素都轉(zhuǎn)換成字符串(如有必要),以便進(jìn)行比較。
如果數(shù)組中有未定義的元素,這些元素將放在數(shù)組的末尾
let a = [1,12,23,14,,undefined,null,NaN,56,6,7,"a",{},[]]; a.sort(); //[[], 1, 12, 14, 23, 56, 6, 7, "NaN", {}, "a", null,undefined,undefined × 1] //返回的NaN已經(jīng)是一個(gè)字符串,說明在比較過程中將其轉(zhuǎn)化成了字符串進(jìn)行比較
仔細(xì)看可以發(fā)現(xiàn),上面順序并沒有按照數(shù)字大小進(jìn)行排序。如果想按照其他標(biāo)準(zhǔn)進(jìn)行排序,就需要提供比較函數(shù)。該函數(shù)比較前后兩個(gè)值,然后返回一個(gè)用于說明這兩個(gè)值的相對順序的數(shù)字。比較函數(shù)應(yīng)該具有兩個(gè)參數(shù) a 和 b,其返回值如下:
若 a 小于 b,在排序后的數(shù)組中 a 應(yīng)該出現(xiàn)在 b 之前,則返回一個(gè)小于 0 的值。
若 a 等于 b,則返回 0。
若 a 大于 b,在排序后的數(shù)組中 a 應(yīng)該出現(xiàn)在 b 之后,則返回一個(gè)大于 0 的值。
let a = [1,12,23,14,,undefined,null,NaN,56,6,7,"a",{},[]]; a.sort((a,b) => {return a - b}); //[null, Array(0), NaN, Object, 1, 6, 7, 12, 14, 23, 56, "a",undefined, undefined × 1]1.4 concat()方法
Array.concat() 方法用于連接兩個(gè)或多個(gè)參數(shù)(數(shù)組,字符串等),該方法不會改變現(xiàn)有的數(shù)組,而會返回連接多個(gè)參數(shù)的一個(gè)新數(shù)組。如果傳入的參數(shù)是數(shù)組,那么它將被展開,將元素添加到返回的數(shù)組中。但要注意,concat并不能遞歸的展開一個(gè)元素為數(shù)組的參數(shù)。
let a = [1,2,3]; let b = a.concat(4,5,[6,7,[9,10]]); // b = [1,2,3,4,5,6,7,[9,10]]];1.5 slice()方法
Array.slice() 方法可從已有的數(shù)組中返回指定的一個(gè)片段(slice),或者說是子數(shù)組。它是從原數(shù)組中截取了一個(gè)片段,并返回到了一個(gè)新數(shù)組。
Array.slice(a,b) 它有兩個(gè)參數(shù)a,b
參數(shù) | 描述 |
---|---|
a | 必選。規(guī)定從何處開始選取。如果是負(fù)數(shù),那么它規(guī)定從數(shù)組尾部開始算起的位置。也就是說,-1 指最后一個(gè)元素,-2 指倒數(shù)第二個(gè)元素,以此類推。 |
b | 可選。規(guī)定從何處結(jié)束選取。該參數(shù)是數(shù)組片斷結(jié)束處的數(shù)組下標(biāo)。如果沒有指定該參數(shù),那么切分的數(shù)組包含從 start 到數(shù)組結(jié)束的所有元素。如果這個(gè)參數(shù)是負(fù)數(shù),那么它規(guī)定的是從數(shù)組尾部開始算起的元素。 |
let a = [1,2,3,4,5,7,8]; let b = a.slice(3); // [4, 5, 7, 8] let c = a.slice(3,5); // [4, 5] let d = a.slice(-5,-2); // [3, 4, 5] let d = a.slice(2,1); // []
請注意,該方法并不會修改數(shù)組,而是返回一個(gè)新的子數(shù)組。如果想刪除數(shù)組中的一段元素,應(yīng)該使用下面這個(gè)方法 Array.splice()。
1.6 splice()方法Array.splice() 方法從數(shù)組中添加/刪除元素,然后返回被刪除的元素。它在原數(shù)組上修改數(shù)組,并不像slice和concat那樣創(chuàng)建新數(shù)組。注意,雖然splice和slice名字非常相似,但是執(zhí)行的卻是完全不同的操作。
參數(shù) | 描述 |
---|---|
index | 必選,整數(shù)。規(guī)定添加/刪除項(xiàng)目的位置,使用負(fù)數(shù)可從數(shù)組結(jié)尾處倒著尋找位置。 |
howmany | 可選,整數(shù)。要刪除的元素?cái)?shù)量。如果設(shè)置為 0,則不會刪除元素。如果沒有選擇,則默認(rèn)從index開始到數(shù)組結(jié)束的所有元素 |
item1, ..., itemX | 可選。向數(shù)組添加新的元素。 |
let a = [1,2,3,4,5,7,8]; let b = a.splice(3); // a = [1,2,3] b = [4, 5, 7, 8] ----------------------------------------------------------- let c = [1,2,3,4,5,7,8]; let d = c.splice(3,5); // c = [1,2] d = [3,4,5,7,8] ----------------------------------------------------------- let e = [1,2,3,4,5,7,8]; let f = e.splice(3,2,111,222,[1,2]); // e = [1, 2, 3, 111, 222,[1,2], 7, 8] f = [4,5]
大家要記住slice()和splice()兩個(gè)方法第二個(gè)參數(shù)代表的意義是不一樣的。雖然這很基礎(chǔ),可是有時(shí)候還是會弄混。
1.7 push()和pop()方法Array.push() 方法可向數(shù)組的末尾添加一個(gè)或多個(gè)元素,并返回新的長度。
Array.pop()方法用于刪除并返回?cái)?shù)組的最后一個(gè)元素。如果數(shù)組已經(jīng)為空,則 pop() 不改變數(shù)組,并返回 undefined 值。
let a = [1,2,3,4,5]; let b = a.pop(); //a = [1,2,3,4] b = 5 let c = a.push(1,3,5); // a = [1,2,3,4,1,3,5] c = 7
上面兩個(gè)方法都是直接對原數(shù)組進(jìn)行操作。通過上面兩個(gè)方法可以實(shí)現(xiàn)一個(gè)先進(jìn)后出的棧。
1.8 unshift和shift()方法unshift,shift()的方法行為和push(),pop()非常相似,只不過他們是對數(shù)組的頭部元素進(jìn)行插入和刪除。
Array.unshift() 方法可向數(shù)組的頭部添加一個(gè)或多個(gè)元素,并返回新的長度。
Array.shift()方法用于刪除并返回?cái)?shù)組的第一個(gè)元素。如果數(shù)組已經(jīng)為空,則 pop() 不改變數(shù)組,并返回 undefined 值。
let a = [1,2,3,4,5]; let b = a.shift(); //a = [2,3,4,5] b = 1 let c = a.unshift(1,3,5); // a = [1,3,5,2,3,45] c = 71.9 toString()和toLocaleString()方法
和所有javascript的對象一樣,數(shù)組也有toString()方法,這個(gè)方法可以將數(shù)組的每一個(gè)元素轉(zhuǎn)化成字符串(如果必要的話,就調(diào)用元素的toString()方法),然后輸出字符串的列表,字符串之間用逗號隔開。(用我的話來理解,其實(shí)就是遍歷數(shù)組元素調(diào)用每個(gè)元素自身的toString()方法,然后用逗號連接)
toString()的返回值和沒有參數(shù)的join()方法返回的字符串相同
let a = let e = [1,undefined,null,Boolean,{},[],function(){console.log(1);}]; let b = a.toString(); // b = "1,,,function Boolean() { [native code] },[object Object],,function (){console.log(1);}"
注意,輸出的結(jié)果中,返回的數(shù)組值周圍沒有括號。
toLocaleString方法是toString()方法的本地化版本。它是使用地區(qū)特定的分隔符把生成的字符串連接起來,形成一個(gè)字符串。
雖然是兩個(gè)方法,但是一般元素兩個(gè)方法的輸出結(jié)果卻基本是一樣的,去網(wǎng)上找了相關(guān)文章,發(fā)現(xiàn)只有兩種情況比較有區(qū)分,一個(gè)是時(shí)間,一個(gè)是4位數(shù)字以上的數(shù)字,舉例如下
let a = 1111; let b = a.toLocaleString(); // b = "1,111" let c = a.toString(); // c = "1111"; ------------------------------------------------------- let date = new Date(); let d = date.toString(); // d = "Sun Sep 03 2017 21:52:18 GMT+0800 (中國標(biāo)準(zhǔn)時(shí)間)" let e = date.toLocaleString(); //e = "2017/9/3 下午9:52:18"
好吧,這個(gè)api和數(shù)組關(guān)系不大。。。主要還是和數(shù)組中元素自身有關(guān)。啊哈哈,尷尬。
1.10 valueOf()Array.valueOf()方法在日常中用的比較少,該方法繼承與Object。javascript中許多內(nèi)置對象都針對自身重寫了該方法,數(shù)組Array.valueOf()直接返回自身。
let a = [1,"1",{},[]]; let b = a.valueOf(); a === b; // true
2 ES5中的數(shù)組方法好啦,關(guān)于ES3的方法就不詳細(xì)描述了,我相信大家基本上都已經(jīng)完全是爛熟于心的那種,唯一可能需要加強(qiáng)記憶的就是一些參數(shù)含義,返回?cái)?shù)據(jù)這些了。
ES5中的數(shù)組方法在各大瀏覽器的兼容性
Opera 11+
Firefox 3.6+
Safari 5+
Chrome 8+
Internet Explorer 9+
2.Array在ES5新增的方法中接受兩個(gè)參數(shù),第一個(gè)參數(shù)都是function類型,必選,默認(rèn)有傳參,這些參數(shù)分別是:
currentValue : 數(shù)組當(dāng)前項(xiàng)的值
index : 數(shù)組當(dāng)前項(xiàng)的索引
array : 數(shù)組對象本身
第二個(gè)參數(shù)是當(dāng)執(zhí)行回調(diào)函數(shù)時(shí)指向的this(參考對象),不提供默認(rèn)為window,嚴(yán)格模式下為undefined。
以forEach舉例
語法
array.forEach(callback, thisArg) array.forEach(callback(currentValue, index, array){ //do something }, thisArg)
例子:
//demo,注意this指向 //我這個(gè)demo沒有用箭頭函數(shù)來測試 let a = ["a", "b", "c"]; a.forEach(function(currentValue, index, array){ this.info(currentValue, index, array); },{info:function(value,index,array){ console.log(`當(dāng)前值${value},下標(biāo)${index},數(shù)組${array}`)} }); function info(value,index,array){ console.log(`外放方法 : 當(dāng)前值${value},下標(biāo)${index},數(shù)組${array}`)} } // 當(dāng)前值a,下標(biāo)0,數(shù)組a,b,c // 當(dāng)前值b,下標(biāo)1,數(shù)組a,b,c // 當(dāng)前值c,下標(biāo)2,數(shù)組a,b,c
3.ES5中的所有關(guān)于遍歷的方法按升序?yàn)閿?shù)組中含有效值的每一項(xiàng)執(zhí)行一次callback函數(shù),那些已刪除(使用delete方法等情況)或者未初始化的項(xiàng)將被跳過(但不包括那些值為 undefined 的項(xiàng))(例如在稀疏數(shù)組上)。
例子:數(shù)組哪些項(xiàng)被跳過了
function logArrayElements(element, index, array) { console.log(`a[${index}] = ${element}`); } let xxx; //定義未賦值 let a = [1,2,"", ,undefined,xxx,3]; delete a[1]; // 移除 2 a.forEach(logArrayElements); // a[0] = 1 // 注意索引1被跳過了,因?yàn)樵跀?shù)組的這個(gè)位置沒有項(xiàng) 被刪除了 // a[2] = "" // 注意索引3被跳過了,因?yàn)樵跀?shù)組的這個(gè)位置沒有項(xiàng),可以理解成沒有被初始化 // a[4] = undefined // a[5] = undefined // a[6] = 3
好了,上面3點(diǎn)基本上是ES5中所有方法的共性,下面就不重復(fù)述說了。開始正文解析每個(gè)方法的不同了
2.1 forEach()Array.forEach() 為每個(gè)數(shù)組元素執(zhí)行callback函數(shù);不像map() 或者reduce() ,它總是返回 undefined值,并且不可鏈?zhǔn)秸{(diào)用。典型用例是在一個(gè)鏈的最后執(zhí)行副作用。
注意: 沒有辦法中止或者跳出 forEach 循環(huán),除了拋出一個(gè)異常。如果你需要跳出函數(shù),推薦使用Array.some。如果可以,新方法 find() 或者findIndex() 也可被用于真值測試的提早終止。
例子:如果數(shù)組在迭代時(shí)被修改了
下面的例子輸出"one", "two", "three"。當(dāng)?shù)竭_(dá)包含值"two"的項(xiàng)時(shí),整個(gè)數(shù)組添加了一個(gè)項(xiàng)在第一位,這導(dǎo)致所有的元素下移一個(gè)位置。此時(shí)在下次執(zhí)行回調(diào)中,因?yàn)樵?"two"符合條件,結(jié)果一直增加元素,直到遍歷次數(shù)完畢。forEach()不會在迭代之前創(chuàng)建數(shù)組的副本。
let a = ["one", "two", "three"]; let b = a.forEach((value,index,arr) => { if (value === "two") { a.unshift("zero"); } return "new" + value }); // one,0,["one", "two", "three"] // two,1,["one", "two", "three"] // two,2,["zero", "one", "two", "three"] // two,3,["zero","zero", "one", "two", "three"]
看完例子可以發(fā)現(xiàn),使用 forEach 方法處理數(shù)組時(shí),數(shù)組元素的范圍是在callback方法第一次調(diào)用之前就已經(jīng)確定了。在 forEach 方法執(zhí)行的過程中:原數(shù)組中新增加的元素將不會被 callback 訪問到;若已經(jīng)存在的元素被改變或刪除了,則它們的傳遞到 callback 的值是 forEach 方法遍歷到它們的那一個(gè)索引時(shí)的值。
2.2 map()ES5中所有API在數(shù)組被修改時(shí)都遵從這個(gè)原則,以下不再重復(fù)
Array.map 方法會給原數(shù)組中的每個(gè)元素都按順序調(diào)用一次callback函數(shù)。callback每次執(zhí)行后的返回值(沒有指定返回值則返回undefined)組合起來形成一個(gè)新數(shù)組。
例子:返回每個(gè)元素的平方根的數(shù)組
let a = [1,4,9]; let b = a.map((value) => { return Math.sqrt(value); //如果沒有return,則默認(rèn)返回undefined }); // b= [1,2,3]2.3 filter()
Array.filter()為數(shù)組中的每個(gè)元素調(diào)用一次 callback 函數(shù),并利用所有使得 callback 返回 true 或 等價(jià)于 true 的值 的元素創(chuàng)建一個(gè)新數(shù)組。那些沒有通過 callback 測試的元素會被跳過,不會被包含在新數(shù)組中
例子:數(shù)組去重
let a = [1,2,3,4,32,6,79,0,1,1,8]; let b = a.filter((value,index,arr) => { return arr.indexOf(value) === index; }); // b = [1, 2, 3, 4, 32, 6, 79, 0, 8]2.4 some()
Array.some 為數(shù)組中的每一個(gè)元素執(zhí)行一次 callback 函數(shù),直到找到一個(gè)使得 callback 返回一個(gè)“真值”(即可轉(zhuǎn)換為布爾值 true 的值)。如果找到了這樣一個(gè)值,some 將會立即返回 true。否則,some 返回 false。callback 只會在那些”有值“的索引上被調(diào)用,不會在那些被刪除或從來未被賦值的索引上調(diào)用。
例子:查看數(shù)組內(nèi)是否含有大于0的元素
let a = [-1,4,9]; let b = a.some((value) => { return value > 0; //如果沒有return,則默認(rèn)返回undefined,將無法告訴some判斷 }); // b = true
2.5 every()some方法可以理解成擁有跳出功能的forEach()函數(shù),可以用在在一些需要中斷函數(shù)的地方
Array.every() 方法為數(shù)組中的每個(gè)元素執(zhí)行一次 callback 函數(shù),直到它找到一個(gè)使 callback 返回 false(表示可轉(zhuǎn)換為布爾值 false 的值)的元素。如果發(fā)現(xiàn)了一個(gè)這樣的元素,every 方法將會立即返回 false。否則,callback 為每一個(gè)元素返回 true,every 就會返回 true。callback 只會為那些已經(jīng)被賦值的索引調(diào)用。不會為那些被刪除或從來沒被賦值的索引調(diào)用。
例子:檢測所有數(shù)組元素的大小,是否都大于0
let a = [-1,4,9]; let b = a.every((value) => { return value > 0; //如果沒有return,則默認(rèn)返回undefined }); // b = false2.6 indexOf()
Array.indexOf()使用嚴(yán)格相等(strict equality,即===)進(jìn)行判斷searchElement與數(shù)組中包含的元素之間的關(guān)系。
Array.indexOf()提供了兩個(gè)參數(shù),第一個(gè)searchElement代表要查詢的元素,第二個(gè)代表fromIndex表示從哪個(gè)下標(biāo)開始查找,默認(rèn)為0。
語法
arr.indexOf(searchElement) arr.indexOf(searchElement, fromIndex = 0)
Array.indexOf()會返回首個(gè)被找到的元素在數(shù)組中的索引位置; 若沒有找到則返回 -1
例子:
let array = [2, 5, 9]; array.indexOf(2); // 0 array.indexOf(7); // -1 array.indexOf(9, 2); // 2 array.indexOf(2, -1); // -1 array.indexOf(2, -3); // 02.7 lastIndexOf()
Array.lastIndexOf()就不細(xì)說了,其實(shí)從名字大家也可以看出來,indexOf是正向順序查找,lastIndexOf是反向從尾部開始查找,但是返回的索引下標(biāo)仍然是正向的順序索引
。
語法
arr.lastIndexOf(searchElement, fromIndex = arr.length - 1)
需要注意的是,只是查找的方向相反,fromIndex和返回的索引都是正向順序的,千萬不要搞混了(感覺我這么一說,大家可能搞混了,捂臉)。
例子:各種情況下的的indexOf
var array = [2, 5, 9, 2]; var index = array.lastIndexOf(2); // index = 3 index = array.lastIndexOf(7); // index = -1 index = array.lastIndexOf(2, 3); // index = 3 index = array.lastIndexOf(2, 2); // index = 0 index = array.lastIndexOf(2, -2); // index = 0 index = array.lastIndexOf(2, -1); // index = 32.8 reduce()
Array.reduce() 為數(shù)組中的每一個(gè)元素依次執(zhí)行回調(diào)函數(shù),最后返回一個(gè)函數(shù)累計(jì)處理的結(jié)果。
語法
array.reduce(function(accumulator, currentValue, currentIndex, array), initialValue)
reduce的回調(diào)函數(shù)中的參數(shù)與前面的不同,多了第一個(gè)參數(shù),是上一次的返回值
accumulator : 上一次調(diào)用回調(diào)返回的值,或者是提供的初始值(initialValue)
currentValue : 數(shù)組當(dāng)前項(xiàng)的值
currentIndex : 數(shù)據(jù)當(dāng)前項(xiàng)的索引。第一次遍歷時(shí),如果提供了 initialValue ,從0開始;否則從1開始
array : 調(diào)用 reduce 的數(shù)組
initialValue : 可選項(xiàng),其值用于第一次調(diào)用 callback 的第一個(gè)參數(shù)。如果沒有設(shè)置初始值,則將數(shù)組中的第一個(gè)元素作為初始值。空數(shù)組調(diào)用reduce時(shí)沒有設(shè)置初始值將會報(bào)錯。
例子:數(shù)組求和
let sum = [0, 1, 2, 3].reduce(function (o,n) { return o + n; }); // sum = 6
對了,當(dāng)回調(diào)函數(shù)第一次執(zhí)行時(shí),accumulator 和 currentValue 的取值有兩種情況:
調(diào)用 reduce 時(shí)提供initialValue,accumulator 取值為 initialValue ,currentValue 取數(shù)組中的第一個(gè)值;
沒有提供 initialValue ,accumulator 取數(shù)組中的第一個(gè)值,currentValue 取數(shù)組中的第二個(gè)值。
例子:reduce數(shù)組去重
[1,2,3,4,5,6,78,4,3,2,21,1].reduce(function(accumulator,currentValue){ if(accumulator.indexOf(currentValue) > -1){ return accumulator; }else{ accumulator.push(currentValue); return accumulator; } },[])
2.9 reduceRight()方法注意 :如果數(shù)組為空并且沒有提供initialValue, 會拋出TypeError 。如果數(shù)組僅有一個(gè)元素并且沒有提供initialValue, 或者有提供initialValue但是數(shù)組為空,那么此唯一值將被返回并且callback不會被執(zhí)行。
Array.reduceRight() 為數(shù)組中的每一個(gè)元素依次執(zhí)行回調(diào)函數(shù),方向相反,從右到左,最后返回一個(gè)函數(shù)累計(jì)處理的結(jié)果。
因?yàn)檫@個(gè)方法和reduce方法基本是一模一樣的,除了方法相反,所以就不詳細(xì)的再寫一遍了
2.10 isArray()方法之所以將這個(gè)方法放在最后,是因?yàn)檫@個(gè)方法和前面的不太一致,是用于確定傳遞的值是否是一個(gè) Array,使用方法也很簡單
例子
let a = Array.isArray([1,2,3]); //true let b = Array.isArray(document.getElementsByTagName("body")); //類數(shù)組也為false
不過感覺除非是臨時(shí)判斷,不然一般也不會用這個(gè)方法去判斷,一般還是下面這種萬金油型的吧。
Object.prototype.toString.call([]).slice(8, -1) === "Array";//true
3 ES6中的數(shù)組方法好啦,關(guān)于ES5的方法基本上就講到這里了,感覺自己在深入去看了一些文章之后,還是有一些額外的收獲的。比如對reduce這個(gè)平時(shí)不常用的方法了解更加深刻了,感覺之前很多遍歷收集數(shù)據(jù)的場景其實(shí)用reduce更加方便。
3.1 ...方法——concat方法的增強(qiáng)不同于es5主要以遍歷方法為主,es6的方法是各式各樣的,不過必須要說一句,在性能上,es6的效率基本上是最低的。
英文名字叫做Spread syntax,中文名字叫做擴(kuò)展運(yùn)算符。這個(gè)方法我不知道怎么描述,感覺更像是原有concat()方法的增強(qiáng),可以配合著解構(gòu)一起使用,大家還是直接看例子感受以下吧
例子:簡單拷貝數(shù)組
//如果是ES5 let c = [7,8,9].concat(a); //如果是ES6 let a = [1,23,4,5,6]; let b = [7,8,9,...a]; // b = [7, 8, 9, 1, 23, 4, 5, 6] ---------------------------------------------------------- //淺拷貝 let c = [{a : 1}]; let d = [...c] d[0].a = 2 c[0].a // 2
可以看到這個(gè)方法對于引用類型仍然是淺復(fù)制,所以對于數(shù)組的深拷貝還是需要用額外的方法,可以看我另外一篇文章
3.2 of()方法Array.of()方法可以將傳入?yún)?shù)以順序的方式返回成一個(gè)新數(shù)組的元素。
let a = Array.of(1, 2, 3); // a = [1, 2, 3]
其實(shí),剛看到這個(gè)api和他的用途,還是比較懵逼的,因?yàn)榭瓷先ミ@個(gè)方法就是直接將傳入的參數(shù)變成一個(gè)數(shù)組之外,就沒有任何區(qū)別了,那么我為什么不直接用以前的寫法去實(shí)現(xiàn)類似的效果呢,比如 let = [1,2,3];而且看上去也更加直接。然后我去翻了下最新的ECMAScript草案,其中有這么一句話
The of function is an intentionally generic factory method; it does not require that its this value be the Array constructor. Therefore it can be transferred to or inherited by other constructors that may be called with a single numeric argument.
自己理解了一下,其實(shí)大概意思就是說為了彌補(bǔ)Array構(gòu)造函數(shù)傳入單個(gè)函數(shù)的不足,所以出了一個(gè)of這個(gè)更加通用的方法,舉個(gè)例子
let a = new Array(1);//a = [undefined × 1] let b = new Array(1,2);// b = [1,2]
大家可以注意到傳入一個(gè)參數(shù)和傳入兩個(gè)參數(shù)的結(jié)果,完全是不一樣的,這就很尷尬了。而為了避免這種尷尬,es6則出了一種通用的of方法,不管你傳入了幾個(gè)參數(shù),都是一種相同類型的輸出結(jié)果。
不過我好奇的是,如果只傳入幾個(gè)參數(shù),為什么不直接let a = [1,2,3];效率和直觀性也更加的高。如果要創(chuàng)建一個(gè)長度的數(shù)組,我肯定還是選let a = new Array(10000),這種形式,實(shí)在沒有感覺到Array.of的實(shí)用場景,希望大家可以給我點(diǎn)指導(dǎo)。
3.2 from()方法Array.from()方法從一個(gè)類似數(shù)組(擁有一個(gè) length 屬性和若干索引屬性的任意對象)或可迭代的對象(String, Array, Map, Set和 Generator)中創(chuàng)建一個(gè)新的數(shù)組實(shí)例。
我們先查看Array.from()的語法
語法
Array.from(arrayLike, mapFn, thisArg)
從語法中,我們可以看出Array.from()最基本的功能是將一個(gè)類數(shù)組的對象轉(zhuǎn)化成數(shù)組,然后通過第二個(gè)和第三個(gè)參數(shù)可以對轉(zhuǎn)化成功后的數(shù)組再次執(zhí)行一次遍歷數(shù)據(jù)map方法,也就是Array.from(obj).map(mapFn, thisArg)。
對了額外說一句,這個(gè)方法的性能很差,和直接的for循環(huán)的性能對比了一下,差了百倍不止。
例子 :將一串?dāng)?shù)字字符串轉(zhuǎn)化為數(shù)組
let a = Array.from("242365463432",(value) => return value * 2); //a = [4, 8, 4, 6, 12, 10, 8, 12, 6, 8, 6, 4]3.4 copyWithin()方法
Array.copyWithin方法,在當(dāng)前數(shù)組內(nèi)部,將指定位置的成員淺復(fù)制到其他位置(會覆蓋原有成員),然后返回當(dāng)前數(shù)組。也就是說,使用這個(gè)方法,會修改當(dāng)前數(shù)組。
這個(gè)方法有點(diǎn)復(fù)雜,光看描述可能大家未必能輕易理解,大家可以先看下語法,再看demo配合理解,而且自己沒有想到這個(gè)方法合適的應(yīng)用場景。網(wǎng)上也沒又看到相關(guān)使用場景。但是講道理,這個(gè)方法設(shè)計(jì)出來,肯定是經(jīng)過深思熟慮的,如果大家有想到,歡迎評論給我,謝謝。
語法
arr.copyWithin(target, start, end) //arr.copyWithin(目標(biāo)索引, 源開始索引, 結(jié)束源索引)
例子
// 將3-4號位復(fù)制到0號位 [1, 2, 3, 4, 5].copyWithin(0, 3, 4); // [4, 2, 3, 4, 5] // 將2-5號位復(fù)制到0號位 [1, 2, 3, 4, 5].copyWithin(0, 2, 5); //[3, 4, 5, 4, 5] // 將1-4號位復(fù)制到4號位 [1, 2, 3, 4, 5].copyWithin(4, 1, 4); //[1, 2, 3, 4, 2]
復(fù)制遵循含頭不含尾原則
第一個(gè)是常規(guī)的例子,大家可以對比看第二個(gè)可以發(fā)現(xiàn),這個(gè)方法是先淺復(fù)制了數(shù)組一部分暫時(shí)存儲起來,然后再從目標(biāo)索引處開始一個(gè)個(gè)覆蓋后面的元素,直到這段復(fù)制的數(shù)組片段全部粘貼完。
再看第三個(gè)例子,可以發(fā)現(xiàn)當(dāng)復(fù)制的數(shù)據(jù)片段從目標(biāo)索引開始粘貼時(shí),如果超過了長度,它將停止粘貼,這說明它不會改變數(shù)據(jù)的 length,但是會改變數(shù)據(jù)本身的內(nèi)容。
Array.copyWithin可以理解成復(fù)制以及粘貼序列這兩者是為一體的操作;即使復(fù)制和粘貼區(qū)域重疊,粘貼的序列也會有拷貝來的值。
3.5 find() 和 findIndex()方法Array.find()方法返回?cái)?shù)組中滿足提供的測試函數(shù)的第一個(gè)元素的值。否則返回 undefined。
Array.findIndex() 方法返回?cái)?shù)組中滿足提供的測試函數(shù)的第一個(gè)元素的值的索引。否則返回 -1。
這兩個(gè)方法其實(shí)使用非常相似,使用場景有點(diǎn)像ES5中Array.some,都是在找到第一個(gè)滿足條件的時(shí)候,跳出循環(huán),區(qū)別的是,三種返回的值完全不一樣,我想這也許是為什么要在ES6中增加這兩個(gè)API的原因吧,可以理解成是數(shù)組的方法的補(bǔ)足。
例子:三個(gè)方法各自的返回值
let a = [1,2,3,4,5].find((item)=>{return item > 3}); // a = 4 返回第一個(gè)符合結(jié)果的值 let b = [1,2,3,4,5].findIndex((item)=>{return item > 3}); // b = 3 返回第一個(gè)符合結(jié)果的下標(biāo) let c = [1,2,3,4,5].some((item)=>{return item > 3}); // c = true 返回是否有符合條件的Boolean值 -----------------不滿足條件-------------------- let a = [1,2,3,4,5].find((item)=>{return item > 6}); // a = undefined let b = [1,2,3,4,5].findIndex((item)=>{return item > 6}); // b = -1 let c = [1,2,3,4,5].some((item)=>{return item > 6}); // c = false
注意:find()和findIndex()方法無法判斷NaN,可以說是內(nèi)部用 ===判斷,不同于ES7中的include方法。不過這個(gè)判斷方式是另外一個(gè)話題,不在本文詳述了,感興趣的同學(xué)可以去查一下。
其實(shí)還可以發(fā)現(xiàn),Array.find() 方法只是返回第一個(gè)符合條件的元素,它的增強(qiáng)版是es5中Array.filter()方法,返回所有符合條件的元素到一個(gè)新數(shù)組中。可以說是當(dāng)用find方法時(shí)考慮跟多的是跳出吧。
我感覺這4個(gè)方法配合相應(yīng)的回調(diào)函數(shù)基本上可以完全覆蓋大多數(shù)需要數(shù)組判斷的場景了,大家覺得呢?
3.5 fill方法Array.fill()方法用一個(gè)固定值填充一個(gè)數(shù)組中從起始索引到終止索引內(nèi)的全部元素,返回原數(shù)組
這個(gè)方法的使用也非常簡單,大家基本上看個(gè)語法和demo就能懂了。需要注意的是,這個(gè)方法是返回?cái)?shù)組本身,還有一點(diǎn)就是,類數(shù)組不能調(diào)用這個(gè)方法,剛剛自己去改了MDN上面的文檔。
語法
arr.fill(value) arr.fill(value, startIndex) arr.fill(value, startIndex, endIndex)
例子
let a = new Array(10); a.fill(1); // a = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; let b = [1,2,34,5,6,7,8].fill(3,4); //b = [1, 2, 34, 5, 3, 3, 3]; let c = [1,2,34,5,6,7,8].fill(3,2,5); // c = [1, 2, 3, 3, 3, 7, 8];
3.6 entries(),keys(),values()方法個(gè)人感覺這個(gè)方法初始化數(shù)組挺有用的,自己每次測試數(shù)據(jù)時(shí),只要new Array(10000).fill(1),比以前遍歷直觀方便多了
Array.entries()將數(shù)組轉(zhuǎn)化成一個(gè)中包含每個(gè)索引的鍵/值對的Array Iterator對象
Array.keys()將數(shù)組轉(zhuǎn)化成一個(gè)中包含每個(gè)索引的鍵的Array Iterator對象
Array.values()將數(shù)組轉(zhuǎn)化成一個(gè)中包含每個(gè)索引的值的Array Iterator對象。
Array.values()方法chrome瀏覽器并不支持,
之所以將這三個(gè)方法放在一起是有原因的額,大家可以看這三個(gè)方法其實(shí)都是一個(gè)數(shù)組轉(zhuǎn)化為一種新的數(shù)據(jù)類型——返回新的Array Iterator對象,唯一區(qū)別的是轉(zhuǎn)化之后的元素不一樣。跟他們的名字一樣,entries()方法轉(zhuǎn)化為全部的鍵值對,key()方法轉(zhuǎn)化為鍵,value()保留值。
例子:觀察各個(gè)迭代器遍歷輸出的東西
Array.entries()
let a = [1,2,3].entries(); for(let i of a){console.log(i);} //[0, 1] //[1, 2] //[2, 3]
Array.keys()
let b = [1,2,3].keys(); for(let i of b){console.log(i);} //0 //1 //2
Array.values()
let c = [1,2,3].values(); for(let i of c){console.log(i);} //1 //2 //3
4 ES7中的數(shù)組方法 4.1 includes()方法關(guān)于迭代器這個(gè)東西,自己說不上什么,因?yàn)樽约簺]有親自用過,如果大家有什么見解課可以評論給我,我來補(bǔ)充和學(xué)習(xí)一下
Array.includes方法返回一個(gè)布爾值,表示某個(gè)數(shù)組是否包含給定的值,如果包含,則返回true,否則返回false,與字符串的includes方法類似。
這個(gè)方法大家可以看作是ES5中Array.indexOf的語義增強(qiáng)版,“includes”這個(gè)是否包含的意思,直接返回Boolean值,比起原來的indexOf是否大于-1,顯得更加直觀,我就是判斷有沒有包含哪個(gè)值
語法,使用方法和indexof一模一樣
arr.includes(searchElement) arr.includes(searchElement, fromIndex)
例子
let array = [2, 5, 9]; array.includes(2); // true array.includes(7); // false array.includes(9, 2); // true array.includes(2, -1); // false array.includes(2, -3); // true
方法還真是tmd多啊,感覺基本上應(yīng)該是更新完了,前后兩星期花了我4天時(shí)間吧,還是挺累的。不過收貨還是很多,比如知道了ES5的方法基本上都有第二個(gè)this指向的參數(shù),重新認(rèn)識了reduce方法,感覺自己之前很多場景用reduce更好,重新熟悉了一些ES6的方法可以試用有些場景
如果能看到最后的,感覺你也是夠累的,哈哈哈。
既然這么累,點(diǎn)顆星吧
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/88489.html
摘要:不幸的是,這種方法在中失效,因?yàn)樗麄儚闹绣e誤的去掉了第一個(gè)空成員。假設(shè)競走的比賽結(jié)果需要保存到數(shù)組中。目的就是將競賽者與他們的記錄時(shí)間交替的放在數(shù)組中。結(jié)論我希望我列出的這幾條應(yīng)用足以說明與是最佳搭檔。 原文地址:http://javascriptweblog.wordpress.com/2010/11/08/javascripts-dream-team-in-praise-of-sp...
摘要:我想自己可以嘗試一下寫一個(gè)低配版的模塊加載器來應(yīng)付一下我這個(gè)單頁網(wǎng)站,當(dāng)然只是大致模仿了主要功能。是這樣處理的模塊依賴,同時(shí)依賴,這種情況下的模塊函數(shù)被調(diào)用時(shí),被傳入的是,所以需要自己在里面手動一下。 Contents 前言 回顧RequireJs的基本用法 實(shí)現(xiàn)原理 使用方法 總結(jié) 前言 前段時(shí)間一直想用單頁開發(fā)技術(shù)寫一個(gè)自己的個(gè)人網(wǎng)站(使用es2015),寫了一部分之后,發(fā)現(xiàn)單...
摘要:它的關(guān)鍵能力,是模塊及依賴管理。其次,保持局部變量風(fēng)格。我們很習(xí)慣通過和這樣的全局變量來訪問這樣的庫,但如果使用,它們都應(yīng)只作為局部變量這里的就只存在于這個(gè)文件的代碼范圍內(nèi)獨(dú)立的作用域。 引言 1. manually 以前,我新開一個(gè)網(wǎng)頁項(xiàng)目,然后想到要用jQuery,我會打開瀏覽器,然后找到j(luò)Query的官方網(wǎng)站,點(diǎn)擊那個(gè)醒目的Download jQuery按鈕,下載到.js文件,然...
摘要:有時(shí)候你寫一個(gè)方法,里面一堆循環(huán),循環(huán)里一堆自己看看都覺得死了其實(shí)人家自帶的方法已經(jīng)寫了,你用一下就好了。好了,撩一張圖。 有時(shí)候你寫一個(gè)方法,里面一堆for循環(huán),for循環(huán)里一堆if else自己看看都覺得low死了其實(shí)人家js自帶的方法已經(jīng)寫了,你用一下就好了。 因?yàn)槲覍慹rp的么,然后就會用到金額,金額的話一般保留兩位小數(shù),然后用千分位顯示,你打算怎么寫,先用小數(shù)點(diǎn)區(qū)分小數(shù)位和整...
摘要:模塊化編程首先,我想說說模塊化編程這個(gè)概念當(dāng)我不清楚這個(gè)概念的時(shí)候,其實(shí)說什么模塊化編程多好多好都是懵逼的而我一直不覺得有多好,其實(shí)也是因?yàn)槲覐拈_始寫,就一直都在模塊化編程啊我們寫一個(gè)文件然后我們在文件中引入然后調(diào)用方法哈哈這樣已經(jīng)是模塊化 模塊化編程 首先,我想說說模塊化編程這個(gè)概念當(dāng)我不清楚這個(gè)概念的時(shí)候,其實(shí)說什么模塊化編程多好多好都是懵逼的而我一直不覺得有多好,其實(shí)也是因?yàn)槲覐?..
閱讀 902·2021-10-25 09:44
閱讀 1279·2021-09-23 11:56
閱讀 1198·2021-09-10 10:50
閱讀 3142·2019-08-30 15:53
閱讀 2145·2019-08-30 13:17
閱讀 629·2019-08-29 18:43
閱讀 2506·2019-08-29 12:57
閱讀 865·2019-08-26 12:20