1.構(gòu)造數(shù)組
字面量方式:
let a = []; //最常用的,簡(jiǎn)潔方便
a.length = 3; // [undefined × 3]
使用構(gòu)造器:
let b = new Array(); //[]
let c = Array(3); //[undefined × 3]
let d = Array(1,2,3); //[1,2,3]
數(shù)組長(zhǎng)度最大為Math.pow(2,32)-1 ,即 4294967295 位
兩種方式性能PK?
new Array() < []
2.Array.of
Array.of用于將參數(shù)依次轉(zhuǎn)化為數(shù)組中的一項(xiàng),然后返回這個(gè)新數(shù)組,而不管這個(gè)參數(shù)是數(shù)字還是其它。它基本上與Array構(gòu)造器功能一致,唯一的區(qū)別就在單個(gè)數(shù)字參數(shù)的處理上。如下:
Array.of(3); // [3]
Array(3); // [undefined × 3]
參數(shù)為多個(gè),或單個(gè)參數(shù)不是數(shù)字時(shí),Array.of 與 Array構(gòu)造器等同:
Array.of(1, 2); // [1, 2]
Array(1, 2); // [1, 2]
Array.of('8'); // ["8"]
Array('8'); // ["8"]
即使其他版本瀏覽器不支持也不必?fù)?dān)心,由于Array.of與Array構(gòu)造器的這種高度相似性,實(shí)現(xiàn)一個(gè)polyfill十分簡(jiǎn)單。如下:
if (!Array.of){
Array.of = function(){
return Array.prototype.slice.call(arguments);
//return [].slice.call(arguments);
};
}
3.Array.from 語(yǔ)法:Array.from(arrayLike, processingFn, thisArg)
Array.from的設(shè)計(jì)初衷是快速便捷的基于其他對(duì)象創(chuàng)建新數(shù)組,準(zhǔn)確來(lái)說(shuō)就是從一個(gè)類似數(shù)組的可迭代對(duì)象創(chuàng)建一個(gè)新的數(shù)組實(shí)例
從語(yǔ)法上看,Array.from擁有3個(gè)形參,第一個(gè)為類似數(shù)組的對(duì)象,必選。第二個(gè)為加工函數(shù),新生成的數(shù)組會(huì)經(jīng)過(guò)該函數(shù)的加工再返回。第三個(gè)為this作用域,表示加工函數(shù)執(zhí)行時(shí)this的值,后兩個(gè)參數(shù)都是可選的。
var obj = {0: 'a', 1: 'b', 2:'c', length: 3};
Array.from(obj, (value) => value.repeat(2), obj); //["aa","bb","cc"]
生成一個(gè)從0到指定數(shù)字的新數(shù)組,Array.from就可以輕易的做到:
Array.from({length: 10}, (v, i) => i); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
4.Array.isArray 用來(lái)判斷一個(gè)變量是否數(shù)組類型
Array.isArray([]); // true
Array.isArray({0: 'a', length: 1}); // false
除了這個(gè)方法還有Object.prototype.toString 判斷是否為數(shù)組
5.方法 unshift、shift、push、pop、splice、reverse、sort,以及兩個(gè)ES6新增的方法flat、flatMap、copyWithin 和 fill, 以上方法會(huì)改變數(shù)組本身。
unshift 語(yǔ)法:arr.unshift(element1, …, elementN)
unshift() 方法用于在數(shù)組開始處插入一些元素(就像是棧底插入),并返回?cái)?shù)組新的長(zhǎng)度。
let array = ["red", "green", "blue"];
let length = array.unshift("yellow");
console.log(array); // ["yellow", "red", "green", "blue"]
console.log(length); // 4
shift 語(yǔ)法:arr.shift()
shift()方法刪除數(shù)組的第一個(gè)元素,并返回這個(gè)元素。
let array = [1,2,3,4,5];
let item = array.shift();
console.log(array); // [2,3,4,5]
console.log(item); // 1
push 語(yǔ)法:arr.push(element1, …, elementN)
push()方法添加一個(gè)或者多個(gè)元素到數(shù)組末尾,并且返回?cái)?shù)組新的長(zhǎng)度。
let array = ["football", "basketball", "volleyball"];
let i = array.push("Table tennis");
console.log(array); // ["football", "basketball", "volleyball", "Table tennis"]
console.log(i); // 4
pop 語(yǔ)法:arr.pop()
pop() 方法刪除一個(gè)數(shù)組中的最后的一個(gè)元素,并且返回這個(gè)元素。
let array = ["cat", "dog", "cow", "chicken", "mouse"];
let item = array.pop();
console.log(array); // ["cat", "dog", "cow", "chicken"]
console.log(item); // mouse
splice 語(yǔ)法:arr.splice(start,deleteCount,[item1, item2, …])
splice()方法用新元素替換舊元素的方式來(lái)修改數(shù)組。
start 為開始位置,如果超過(guò)了數(shù)組長(zhǎng)度,則從數(shù)組末尾開始添加內(nèi)容;如果是負(fù)值,則其指定的索引位置等同于 length+start (length為數(shù)組的長(zhǎng)度),表示從數(shù)組末尾開始的第 -start 位。
deleteCount 指定要?jiǎng)h除的元素個(gè)數(shù),若等于0,則不刪除。這種情況下,至少應(yīng)該添加一位新元素,若大于start之后的元素總和,則start及之后的元素都將被刪除。
itemN 指定新增的元素,如果缺省,則該方法只刪除數(shù)組元素。
返回值 由原數(shù)組中被刪除元素組成的數(shù)組,如果沒有刪除,則返回一個(gè)空數(shù)組。
let array = ["apple","boy"];
let splices = array.splice(-3,1,"cat");
console.log(array); // ["cat", "boy"]
console.log(splices); // ["apple"], 可見即使-start超出數(shù)組長(zhǎng)度,數(shù)組默認(rèn)從首位開始刪除
------
let array = ["apple","boy"];
let splices = array.splice(3,3,"cat");
console.log(array); // ['apple', 'boy', 'cat']
console.log(splices); // []
可見當(dāng)start超出數(shù)組長(zhǎng)度,數(shù)組沒變化,默認(rèn)從末尾該添加啥添加啥
reverse 語(yǔ)法:arr.reverse()
reverse()方法顛倒數(shù)組中元素的位置,第一個(gè)會(huì)成為最后一個(gè),最后一個(gè)會(huì)成為第一個(gè),該方法返回對(duì)數(shù)組的引用。
let array = [1,2,3,4,5];
let array2 = array.reverse();
console.log(array); // [5,4,3,2,1]
console.log(array2===array); // true
sort 語(yǔ)法:arr.sort([comparefn])
sort()方法對(duì)數(shù)組元素進(jìn)行排序,并返回這個(gè)數(shù)組。
comparefn是可選的,如果省略,數(shù)組元素將按照各自轉(zhuǎn)換為字符串的Unicode(萬(wàn)國(guó)碼)位點(diǎn)順序排序,例如”Boy”將排到”apple”之前。當(dāng)對(duì)數(shù)字排序的時(shí)候,25將會(huì)排到8之前,因?yàn)檗D(zhuǎn)換為字符串后,”25”將比”8”靠前。例如:
let array = ["Boy","apple","Cat","dog"];
let array2 = array.sort();
console.log(array); // ["Boy", "Cat", "apple", "dog"]
console.log(array2 == array); // true
let array3 = array.sort((a, b) => a.localeCompare(b));
console.log(array3)//["apple", "Boy", "Cat", "dog"]
let array = [10, 1, 3, 20];
let array1 = array.sort();
console.log(array1); // [1, 10, 20, 3]
let array2 = array.sort((a, b) => a-b);
console.log(array2)//[1, 3, 10, 20]
實(shí)際上,ECMAscript規(guī)范中并未規(guī)定具體的sort算法,這就勢(shì)必導(dǎo)致各個(gè)瀏覽器不盡相同的sort算法,請(qǐng)看sort方法在Chrome瀏覽器下表現(xiàn):
let array = [{ n: "a", v: 1 }, { n: "b", v: 1 }, { n: "c", v: 1 }, { n: "d", v: 1 }, { n: "e", v: 1 }, { n: "f", v: 1 }, { n: "g", v: 1 }, { n: "h", v: 1 }, { n: "i", v: 1 }, { n: "j", v: 1 }, { n: "k", v: 1 }, ];
array.sort((a, b) => return a.v - b.v);
for (let i = 0,len = array.length; i < len; i++) {
console.log(array[i].n);
}
由于v值相等,array數(shù)組排序前后應(yīng)該不變,然而Chrome卻表現(xiàn)異常,而其他瀏覽器(如IE 或 Firefox) 表現(xiàn)正常。
這是因?yàn)関8引擎為了高效排序(采用了不穩(wěn)定排序)。即數(shù)組長(zhǎng)度超過(guò)10條時(shí),會(huì)調(diào)用另一種排序方法(快速排序);而10條及以下采用的是插入排序,此時(shí)結(jié)果將是穩(wěn)定的。
解決辦法:
// 由于快速排序會(huì)打亂值相同的元素的默認(rèn)排序,因此我們需要先標(biāo)記元素的默認(rèn)位置
array.forEach((v, k) =>v.__index = k);
// 由于__index標(biāo)記了初始順序,這樣的返回才保證了值相同元素的順序不變,進(jìn)而使得排序穩(wěn)定
array.sort((a, b) => return a.v - b.v || a.__index - b.__index);
值得注意的是:
各瀏覽器的針對(duì)sort方法內(nèi)部算法實(shí)現(xiàn)不盡相同,排序函數(shù)盡量只返回-1、0、1三種不同的值,不要嘗試返回true或false等其它數(shù)值,因?yàn)榭赡軐?dǎo)致不可靠的排序結(jié)果。
let array = [7, 6, 5, 4, 3, 2, 1, 0, 10, 9, 8];
let comparefn = (x, y) => x > y;
array.sort(comparefn);
flat 語(yǔ)法:arr.flat(depth)
flat() 方法會(huì)按照一個(gè)可指定的深度遞歸遍歷數(shù)組,并將所有元素與遍歷到的子數(shù)組中的元素合并為一個(gè)新數(shù)組返回。
var arr1 = [1, 2, [3, 4]];
arr1.flat();
// [1, 2, 3, 4]
var arr2 = [1, 2, [3, 4, [5, 6]]];
arr2.flat(2);
// [1, 2, 3, 4, 5, 6]
//使用 Infinity 作為深度,展開任意深度的嵌套數(shù)組
arr2.flat(Infinity);
// [1, 2, 3, 4, 5, 6]
var arr4 = [1, 2, , 4, 5];
arr4.flat(); //flat() 方法會(huì)移除數(shù)組中的空項(xiàng):
// [1, 2, 4, 5]
flatMap 語(yǔ)法:arr.flatMap(fn,thisArg)
flatMap() 方法首先使用映射函數(shù)映射每個(gè)元素,然后將結(jié)果壓縮成一個(gè)新數(shù)組。它與 map 和 深度值1的 flat 幾乎相同,但 flatMap 通常在合并成一種方法的效率稍微高一些。
var arr1 = [1, 2, 3, 4];
arr1.flatMap(x => [x * 2]);
// [2, 4, 6, 8]
// 只會(huì)將 flatMap 中的函數(shù)返回的數(shù)組 “壓平” 一層
arr1.flatMap(x => [[x * 2]]);
// [[2], [4], [6], [8]]
copyWithin(ES6) 語(yǔ)法:arr.copyWithin(target, start, end)
copyWithin() 方法基于ECMAScript 2015(ES6)規(guī)范,用于數(shù)組內(nèi)元素之間的替換,即替換元素和被替換元素均是數(shù)組內(nèi)的元素。
其中,taget 指定被替換元素的索引,start 指定替換元素起始的索引,end 可選,指的是替換元素結(jié)束位置的索引。
如果start為負(fù),則其指定的索引位置等同于length+start,length為數(shù)組的長(zhǎng)度。end也是如此。
let array = [1,2,3,4,5];
let array2 = array.copyWithin(0,3);
console.log(array===array2,array2); // true [4, 5, 3, 4, 5]
let array = [1,2,3,4,5];
console.log(array.copyWithin(0,3,4)); // [4, 2, 3, 4, 5]
let array = [1,2,3,4,5];
console.log(array.copyWithin(0,-2,-1)); // [4, 2, 3, 4, 5]
fill(ES6) 語(yǔ)法:arr.fill(value, start, end)
fill() 方法基于ECMAScript 2015(ES6)規(guī)范,它同樣用于數(shù)組元素替換,但與copyWithin略有不同,它主要用于將數(shù)組指定區(qū)間內(nèi)的元素替換為某個(gè)值。
其中,value 指定被替換的值,start 指定替換元素起始的索引,end 可選,指的是替換元素結(jié)束位置的索引。
如果start為負(fù),則其指定的索引位置等同于length+start,length為數(shù)組的長(zhǎng)度。end也是如此。
let array = [1,2,3,4,5];
let array2 = array.fill(10,0,3);
console.log(array===array2,array2); // true [10, 10, 10, 4, 5], 可見數(shù)組區(qū)間[0,3]的元素全部替換為10
6. concat、join、slice、toString、toLocateString、indexOf、lastIndexOf、未標(biāo)準(zhǔn)的toSource以及ES7新增的方法includes,不會(huì)改變自身的方法
concat 語(yǔ)法:arr.concat(value1, value2, …, valueN)
concat() 方法將傳入的數(shù)組或者元素與原數(shù)組合并,組成一個(gè)新的數(shù)組并返回。
let array = [1, 2, 3];
let array2 = array.concat(4,[5,6],[7,8,9]);
console.log(array2); // [1, 2, 3, 4, 5, 6, 7, 8, 9]
console.log(array); // [1, 2, 3], 可見原數(shù)組并未被修改
若concat方法中不傳入?yún)?shù),那么將基于原數(shù)組淺復(fù)制生成一個(gè)一模一樣的新數(shù)組(指向新的地址空間)。
let array = [{a: 1}];
let array3 = array.concat();
console.log(array3); // [{a: 1}]
console.log(array3 === array); // false
console.log(array[0] === array3[0]); // true,新舊數(shù)組第一個(gè)元素依舊共用一個(gè)同一個(gè)對(duì)象的引用
join 語(yǔ)法:arr.join([separator = ‘,’]) separator可選,缺省默認(rèn)為逗號(hào)。
join() 方法將數(shù)組中的所有元素連接成一個(gè)字符串。
let array = ['We', 'are', 'Chinese'];
console.log(array.join()); // "We,are,Chinese"
console.log(array.join('+')); // "We+are+Chinese"
console.log(array.join('')); // "WeareChinese"
slice 語(yǔ)法:arr.slice(start, end)
slice() 方法將數(shù)組中一部分元素淺復(fù)制存入新的數(shù)組對(duì)象,并且返回這個(gè)數(shù)組對(duì)象。
參數(shù) start 指定復(fù)制開始位置的索引,end如果有值則表示復(fù)制結(jié)束位置的索引(不包括此位置)。
如果 start 的值為負(fù)數(shù),假如數(shù)組長(zhǎng)度為 length,則表示從 length+start 的位置開始復(fù)制,此時(shí)參數(shù) end 如果有值,只能是比 start 大的負(fù)數(shù),否則將返回空數(shù)組。
slice方法參數(shù)為空時(shí),同concat方法一樣,都是淺復(fù)制生成一個(gè)新數(shù)組。
let array = ["one", "two", "three","four", "five"];
console.log(array.slice()); // ["one", "two", "three","four", "five"]
console.log(array.slice(2,3)); // ["three"]
let array = [{color:"yellow"}, 2, 3];
let array2 = array.slice(0,1);
console.log(array2); // [{color:"yellow"}]
array[0]["color"] = "blue";
console.log(array2); // [{color:"bule"}]
toString 語(yǔ)法:arr.toString()
toString() 方法返回?cái)?shù)組的字符串形式,該字符串由數(shù)組中的每個(gè)元素的 toString() 返回值經(jīng)調(diào)用 join() 方法連接(由逗號(hào)隔開)組成。
let array = ['Jan', 'Feb', 'Mar', 'Apr'];
let str = array.toString();
console.log(str); // Jan,Feb,Mar,Apr
toLocaleString 語(yǔ)法:arr.toLocaleString()
toLocaleString() 類似toString()的變型,該字符串由數(shù)組中的每個(gè)元素的 toLocaleString() 返回值經(jīng)調(diào)用 join() 方法連接(由逗號(hào)隔開)組成。
let array= [{name:'zz'}, 123, "abc", new Date()];
let str = array.toLocaleString();
console.log(str); // [object Object],123,abc,2019/3/28 下午12:16:23
toString()和toLocaleString()兩點(diǎn)區(qū)別:
1.當(dāng)數(shù)字是四位數(shù)及以上時(shí)
let a=1234.5678
a.toString()//"1234.5678"
a.toLocaleString()//"1,234.568"
2.當(dāng)目標(biāo)是標(biāo)準(zhǔn)時(shí)間格式時(shí)
let sd=new Date()//Thu Mar 07 2019 12:11:55 GMT+0800 (中國(guó)標(biāo)準(zhǔn)時(shí)間)
sd.toLocaleString()//"2019/3/7 下午12:21:55"
sd.toString()//Thu Mar 07 2019 12:11:55 GMT+0800
indexOf 語(yǔ)法:arr.indexOf(element, fromIndex=0)
indexOf() 方法用于查找元素在數(shù)組中第一次出現(xiàn)時(shí)的索引,如果沒有,則返回-1。
element 為需要查找的元素,fromIndex 為開始查找的位置,缺省默認(rèn)為0。如果超出數(shù)組長(zhǎng)度,則返回-1。如果為負(fù)值,假設(shè)數(shù)組長(zhǎng)度為length,則從數(shù)組的第 length + fromIndex項(xiàng)開始往數(shù)組末尾查找,如果length + fromIndex<0 則整個(gè)數(shù)組都會(huì)被查找。
let array = ['abc', 'def', 'ghi','123'];
console.log(array.indexOf('def')); // 1
console.log(array.indexOf('def',-1)); // -1 此時(shí)表示從最后一個(gè)元素往后查找,因此查找失敗返回-1
console.log(array.indexOf('def',-4)); // 1 由于4大于數(shù)組長(zhǎng)度,此時(shí)將查找整個(gè)數(shù)組,因此返回1
console.log(array.indexOf(123)); // -1, 由于是嚴(yán)格匹配,因此并不會(huì)匹配到字符串'123'
lastIndexOf 語(yǔ)法:arr.lastIndexOf(element, fromIndex=length-1)
lastIndexOf() 方法用于查找元素在數(shù)組中最后一次出現(xiàn)時(shí)的索引,如果沒有,則返回-1。并且它是indexOf的逆向查找,即從數(shù)組最后一個(gè)往前查找。
element 為需要查找的元素,fromIndex 為開始查找的位置,缺省默認(rèn)為arr.length-1。如果超出數(shù)組長(zhǎng)度,則返回-1。如果為負(fù)值,假設(shè)數(shù)組長(zhǎng)度為length,則從數(shù)組的第 length + fromIndex項(xiàng)開始往數(shù)組棧底查找,如果length + fromIndex<0 則整個(gè)數(shù)組都會(huì)被查找。
同 indexOf 一樣,lastIndexOf 也是嚴(yán)格匹配數(shù)組元素。
includes(ES7) 語(yǔ)法:arr.includes(element, fromIndex=0)
includes() 方法基于ECMAScript 2016(ES7)規(guī)范,它用來(lái)判斷當(dāng)前數(shù)組是否包含某個(gè)指定的值,如果是,則返回 true,否則返回 false。
element 為需要查找的元素,fromIndex 表示從該索引位置開始查找 element,缺省為0,它是正向查找,即從索引處往數(shù)組末尾查找。
let array = [0, 1, 2];
console.log(array.includes(0)); // true
console.log(array.includes(1)); // true
console.log(array.includes(2,-4)); // true
你可能會(huì)問(wèn),既然有了indexOf方法,為什么又造一個(gè)includes方法,arr.indexOf(x)>-1不就等于arr.includes(x)?看起來(lái)是的,幾乎所有的時(shí)候它們都等同,唯一的區(qū)別就是includes能夠發(fā)現(xiàn)NaN,而indexOf不能。
let array = [NaN];
console.log(array.includes(NaN)); // true
console.log(arra.indexOf(NaN)>-1); // false
7. 基于ES6,不會(huì)改變自身的方法一共有12個(gè),分別為forEach、every、some、filter、map、reduce、reduceRight 以及ES6新增的方法entries、find、findIndex、keys、values。
forEach 語(yǔ)法:arr.forEach(fn(value, index,array), thisArg)
forEach() 方法指定數(shù)組的每項(xiàng)元素都執(zhí)行一次傳入的函數(shù),返回值為undefined。
fn 表示在數(shù)組每一項(xiàng)上執(zhí)行的函數(shù),接受三個(gè)參數(shù):
value 當(dāng)前正在被處理的元素的值
index 當(dāng)前元素的數(shù)組索引
array 數(shù)組本身
thisArg 可選,用來(lái)當(dāng)做fn函數(shù)內(nèi)的this對(duì)象。
forEach 將為數(shù)組中每一項(xiàng)執(zhí)行一次 fn 函數(shù),那些已刪除,新增或者從未賦值的項(xiàng)將被跳過(guò)(但不包括值為 undefined 的項(xiàng))。
let array = [1, 3, 5];
let obj = {name:'cc'};
let sReturn = array.forEach(function(value, index, array){
array[index] = value * value;
console.log(this.name); // cc被打印了三次
},obj);
console.log(array); // [1, 9, 25], 可見原數(shù)組改變了
console.log(sReturn); // undefined, 可見返回值為undefined
*forEach無(wú)法直接退出循環(huán),只能使用return 來(lái)達(dá)到for循環(huán)中continue的效果
*它總是返回 undefined值,即使你return了一個(gè)值。
1. 對(duì)于空數(shù)組是不會(huì)執(zhí)行回調(diào)函數(shù)的
2. 對(duì)于已在迭代過(guò)程中刪除的元素,或者空元素會(huì)跳過(guò)回調(diào)函數(shù)
3. 遍歷次數(shù)再第一次循環(huán)前就會(huì)確定,再添加到數(shù)組中的元素不會(huì)被遍歷。
4. 如果已經(jīng)存在的值被改變,則傳遞給 callback 的值是遍歷到他們那一刻的值。
eg:
let a = [1, 2, ,3]; // 最后第二個(gè)元素是空的,不會(huì)遍歷(undefined、null會(huì)遍歷)
let obj = { name: 'obj的名字' };
let result = a.forEach(function (value, index, array) {
a[3] = '改變?cè)?;
a.push('添加到尾端,不會(huì)被遍歷')
console.log(value, 'forEach傳遞的第一個(gè)參數(shù)'); // 分別打印 1 ,2 ,改變?cè)? console.log(this.name); // 'obj的名字' 打印三次 this綁定在obj對(duì)象上
// break; // break會(huì)報(bào)錯(cuò)
return value; // return只能結(jié)束本次回調(diào) 會(huì)執(zhí)行下次回調(diào)
console.log('不會(huì)執(zhí)行,因?yàn)閞eturn 會(huì)執(zhí)行下一次循環(huán)回調(diào)')
}, obj);
console.log(result); // 即使return了一個(gè)值,也還是返回undefined
every 語(yǔ)法:arr.every(fn, thisArg)
every()方法檢測(cè)數(shù)組所有元素是否都符合判斷條件(參數(shù)同上)
方法返回值規(guī)則:
1 ,如果數(shù)組中檢測(cè)到有一個(gè)元素不滿足,則整個(gè)表達(dá)式返回 false,且剩余的元素不會(huì)再進(jìn)行檢測(cè)
2. 如果所有元素都滿足條件,則返回 true
eg:
function isBigEnough(element, index, array) {
return element >= 10; // 判斷數(shù)組中的所有元素是否都大于10
}
[12, 5, 8, 130, 44].every(x => x >= 10); // false
[12, 54, 18, 130, 44].every(x => x >= 10); // true
some 語(yǔ)法:arr.some(fn, thisArg)
some()數(shù)組中的是否有滿足判斷條件的元素(參數(shù)同上)
方法返回值規(guī)則:
1 ,如果有一個(gè)元素滿足條件,則表達(dá)式返回true, 剩余的元素不會(huì)再執(zhí)行檢測(cè)
2. 如果沒有滿足條件的元素,則返回false
eg:
function isBigEnough(element, index, array) {
return (element >= 10); //數(shù)組中是否有一個(gè)元素大于 10
}
let result = [2, 5, 8, 1, 4].some(isBigEnough); // false
let result = [12, 5, 8, 1, 4].some(isBigEnough); // true
filter 語(yǔ)法:arr.filter(fn, thisArg)
filter()過(guò)濾原始數(shù)組,返回通過(guò)所提供函數(shù)實(shí)現(xiàn)的所有元素組成的新數(shù)組(參數(shù)同上)
eg:
let a = [32, 33, 16, 40];
let result = a.filter(function (value, index, array) {
return value >= 18; // 返回a數(shù)組中所有大于18的元素
});
console.log(result,a);// [32,33,40] [32,33,16,40]
map 語(yǔ)法:arr.map(fn, thisArg)
map()對(duì)數(shù)組中的每個(gè)元素進(jìn)行處理,返回新的數(shù)組(參數(shù)同上)
eg:
let a = ['1','2','3','4'];
let result = a.map(function (value, index, array) {
return value + 0
});
console.log(result); //["10", "20", "30", "40"]
reduce 語(yǔ)法:array.reduce(function(total, currentValue, currentIndex, arr), initialValue)
reduce()為數(shù)組提供累加器,合并為一個(gè)值
1. 如果 initialValue 在調(diào)用 reduce 時(shí)被提供,那么第一個(gè) total 將等于 initialValue,此時(shí) currentValue 等于數(shù)組中的第一個(gè)值
2. 如果 initialValue 未被提供,那么 total 等于數(shù)組中的第一個(gè)值,currentValue 等于數(shù)組中的第二個(gè)值。此時(shí)如果數(shù)組為空,那么將拋出 TypeError
3. 如果數(shù)組僅有一個(gè)元素,并且沒有提供 initialValue,或提供了 initialValue 但數(shù)組為空,那么回調(diào)不會(huì)被執(zhí)行,數(shù)組的唯一值將被返回
eg:
// 數(shù)組求和
let sum = [0, 1, 2, 3].reduce(function (a, b) {
return a + b;
}, 0);
// 6
------
// 將二維數(shù)組轉(zhuǎn)化為一維 將數(shù)組元素展開//見flat()
let flattened = [[0, 1], [2, 3], [4, 5]].reduce((a, b) => a.concat(b),[]);
// [0, 1, 2, 3, 4, 5]
reduceRight 語(yǔ)法:array.reduceRight(function(total, currentValue, currentIndex, arr), initialValue)
這個(gè)方法除了與reduce執(zhí)行方向相反外,其他完全與其一致
ES6 keys()&values()&entries() 遍歷鍵名、遍歷鍵值、遍歷鍵名+鍵值
三個(gè)方法都返回一個(gè)新的 Array Iterator 對(duì)象,對(duì)象根據(jù)方法不同包含不同的值
eg:
for (let index of ['a', 'b'].keys()) {
console.log(index);
}
// 0
// 1
for (let elem of ['a', 'b'].values()) {
console.log(elem);
}
// 'a'
// 'b'
for (let [index, elem] of ['a', 'b'].entries()) {
console.log(index, elem);
}
// 0 "a"
// 1 "b"
在for..of中如果遍歷中途要退出,可以使用break退出循環(huán)。
如果不使用for...of循環(huán),可以手動(dòng)調(diào)用遍歷器對(duì)象的next方法,進(jìn)行遍歷:
let letter = ['a', 'b', 'c'];
let entries = letter.entries();
console.log(entries.next().value); // [0, 'a']
console.log(entries.next().value); // [1, 'b']
console.log(entries.next().value); // [2, 'c']
ES6 find()& findIndex() 根據(jù)條件找到數(shù)組成員 語(yǔ)法:arr.find(fn, thisArg),arr.findIndex(fn, thisArg)
find()定義:用于找出第一個(gè)符合條件的數(shù)組成員,并返回該成員,如果沒有符合條件的成員,則返回undefined。
findIndex()定義:返回第一個(gè)符合條件的數(shù)組成員的位置,如果所有成員都不符合條件,則返回-1。
這兩個(gè)方法都可以識(shí)別NaN,彌補(bǔ)了indexOf的不足.
eg:
// find
let a = [1, 4, -5, 10].find((n) => n < 0); // 返回元素-5
let b = [1, 4, -5, 10,NaN].find((n) => Object.is(NaN, n)); // 返回元素NaN
// findIndex
let a = [1, 4, -5, 10].findIndex((n) => n < 0); // 返回索引2
let b = [1, 4, -5, 10,NaN].findIndex((n) => Object.is(NaN, n)); // 返回索引4
8.擴(kuò)展運(yùn)算符
擴(kuò)展運(yùn)算符(spread)是三個(gè)點(diǎn)(...)。它好比 rest 參數(shù)的逆運(yùn)算,將一個(gè)數(shù)組轉(zhuǎn)為用逗號(hào)分隔的參數(shù)序列。
console.log(1, ...[2, 3, 4], 5)
// 1 2 3 4 5
擴(kuò)展運(yùn)算符后面可以放置表達(dá)式。
console.log((...[1, 2]))
注意,擴(kuò)展運(yùn)算符如果放在括號(hào)中,JavaScript引擎就會(huì)認(rèn)為這是函數(shù)調(diào)用。如果這時(shí)不是函數(shù)調(diào)用,就會(huì)報(bào)錯(cuò)。
// Uncaught SyntaxError: Unexpected number
替代函數(shù)的 apply 方法
由于擴(kuò)展運(yùn)算符可以展開數(shù)組,所以不再需要apply方法,將數(shù)組轉(zhuǎn)為函數(shù)的參數(shù)了。
// ES5 的寫法
function f(x, y, z) {
// ...
}
var args = [0, 1, 2];
f.apply(null, args);
// ES6的寫法
function f(x, y, z) {
// ...
}
let args = [0, 1, 2];
f(...args);
下面是擴(kuò)展運(yùn)算符取代apply方法的一個(gè)實(shí)際的例子,應(yīng)用Math.max方法,簡(jiǎn)化求出一個(gè)數(shù)組最大元素的寫法。
// ES5 的寫法
Math.max.apply(null, [14, 3, 77])
// ES6 的寫法
Math.max(...[14, 3, 77])
// 等同于
Math.max(14, 3, 77);
另一個(gè)例子是通過(guò)push函數(shù),將一個(gè)數(shù)組添加到另一個(gè)數(shù)組的尾部。
// ES5的 寫法
var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
Array.prototype.push.apply(arr1, arr2);
// ES6 的寫法
let arr1 = [0, 1, 2];
let arr2 = [3, 4, 5];
arr1.push(...arr2);
還有一個(gè)小例子
// ES5
new (Date.bind.apply(Date, [null, 2015, 1, 1]))
// ES6
new Date(...[2015, 1, 1]);
擴(kuò)展運(yùn)算符的應(yīng)用
(1)復(fù)制數(shù)組
ES5:
const a1 = [1, 2];
const a2 = a1.concat();
a2[0] = 2;
a1 // [1, 2]
使用擴(kuò)展運(yùn)算符:
const a1 = [1, 2];
// 寫法一
const a2 = [...a1];
// 寫法二
const [...a2] = a1;
(2)合并數(shù)組
const a1 = [{ foo: 1 }];
const a2 = [{ bar: 2 }];
const a3 = a1.concat(a2);
const a4 = [...a1, ...a2];
這兩種方法都是淺拷貝
a3[0] === a1[0] // true
a4[0] === a1[0] // true
(3)與解構(gòu)賦值結(jié)合
// ES5
a = list[0], rest = list.slice(1)
// ES6
[a, ...rest] = list
const [first, ...rest] = [1, 2, 3, 4, 5];
first // 1
rest // [2, 3, 4, 5]
const [first, ...rest] = [];
first // undefined
rest // []
注意:如果將擴(kuò)展運(yùn)算符用于數(shù)組賦值,只能放在參數(shù)的最后一位,否則會(huì)報(bào)錯(cuò)。
const [...butLast, last] = [1, 2, 3, 4, 5];
// 報(bào)錯(cuò)
const [first, ...middle, last] = [1, 2, 3, 4, 5];
// 報(bào)錯(cuò)
(4)字符串
擴(kuò)展運(yùn)算符還可以將字符串轉(zhuǎn)為真正的數(shù)組。
[...'hello']
// [ "h", "e", "l", "l", "o" ]
'x\uD83D\uDE80y'.length // 4
[...'x\uD83D\uDE80y'].length // 3
上面代碼的第一種寫法,JavaScript 會(huì)將四個(gè)字節(jié)的 Unicode 字符,
識(shí)別為 2 個(gè)字符,采用擴(kuò)展運(yùn)算符就沒有這個(gè)問(wèn)題。
因此,正確返回字符串長(zhǎng)度的函數(shù),可以像下面這樣寫。
function length(str) {
return [...str].length;
}
length('x\uD83D\uDE80y') // 3
(5)實(shí)現(xiàn)了 Iterator 接口的對(duì)象
任何定義了遍歷器(Iterator)接口的對(duì)象都可以用擴(kuò)展運(yùn)算符轉(zhuǎn)為真正的數(shù)組。
下面代碼中,先定義了Number對(duì)象的遍歷器接口,擴(kuò)展運(yùn)算符將5自動(dòng)轉(zhuǎn)成
Number實(shí)例以后,就會(huì)調(diào)用這個(gè)接口,就會(huì)返回自定義的結(jié)果。
Number.prototype[Symbol.iterator] = function*() {
let i = 0;
let num = this.valueOf();
while (i < num) {
yield i++;
}
}
console.log([...5]) // [0, 1, 2, 3, 4]
下面代碼中,arrayLike是一個(gè)類似數(shù)組的對(duì)象,但是沒有部署Iterator接口
,擴(kuò)展運(yùn)算符就會(huì)報(bào)錯(cuò)。
let arrayLike = {
'0': 'a',
'1': 'b',
'2': 'c',
length: 3
};
// TypeError: Cannot spread non-iterable object.
let arr = [...arrayLike];
(6)Map 和 Set 結(jié)構(gòu),Generator 函數(shù)
擴(kuò)展運(yùn)算符內(nèi)部調(diào)用的是數(shù)據(jù)結(jié)構(gòu)的 Iterator 接口,
因此只要具有 Iterator 接口的對(duì)象,都可以使用擴(kuò)展運(yùn)算符,比如 Map 結(jié)構(gòu)。
let map = new Map([
[1, 'one'],
[2, 'two'],
[3, 'three'],
]);
let arr = [...map.keys()]; // [1, 2, 3]
Generator 函數(shù)運(yùn)行后,返回一個(gè)遍歷器對(duì)象,因此也可以使用擴(kuò)展運(yùn)算符。
const go = function*(){
yield 1;
yield 2;
yield 3;
};
[...go()] // [1, 2, 3]
上面代碼中,變量go是一個(gè) Generator 函數(shù),執(zhí)行后返回的是一個(gè)遍歷器對(duì)象,
對(duì)這個(gè)遍歷器對(duì)象執(zhí)行擴(kuò)展運(yùn)算符,就會(huì)將內(nèi)部遍歷得到的值,轉(zhuǎn)為一個(gè)數(shù)組。
9.數(shù)組的空位
Array(3) // [, , ,]
空位不是undefined,一個(gè)位置的值等于undefined,依然是有值的。空位是沒有任何值,in運(yùn)算符可以說(shuō)明這一點(diǎn)。
0 in [undefined, undefined, undefined] // true
0 in [, , ,] // false
ES5 對(duì)空位的處理,已經(jīng)很不一致了,大多數(shù)情況下會(huì)忽略空位。
forEach(), filter(), reduce(), every() 和some()都會(huì)跳過(guò)空位。
map()會(huì)跳過(guò)空位,但會(huì)保留這個(gè)值
join()和toString()會(huì)將空位視為undefined,而undefined和null會(huì)被處理成空字符串。
// 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 則是明確將空位轉(zhuǎn)為undefined。
Array.from方法會(huì)將數(shù)組的空位,轉(zhuǎn)為undefined,也就是說(shuō),這個(gè)方法不會(huì)忽略空位。
Array.from(['a',,'b'])
// [ "a", undefined, "b" ]
擴(kuò)展運(yùn)算符(...)也會(huì)將空位轉(zhuǎn)為undefined。
[...['a',,'b']]
// [ "a", undefined, "b" ]
copyWithin()會(huì)連空位一起拷貝
[,'a','b',,].copyWithin(2,0) // [,"a",,"a"]
fill()會(huì)將空位視為正常的數(shù)組位置。
new Array(3).fill('a') // ["a","a","a"]
for...of循環(huán)也會(huì)遍歷空位。
let arr = [, ,];
for (let i of arr) {
console.log(1);
}
// 1
// 1
entries()、keys()、values()、find()和findIndex()會(huì)將空位處理成undefined。
// entries()
[...[,'a'].entries()] // [[0,undefined], [1,"a"]]
// keys()
[...[,'a'].keys()] // [0,1]
// values()
[...[,'a'].values()] // [undefined,"a"]
// find()
[,'a'].find(x => true) // undefined
// findIndex()
[,'a'].findIndex(x => true) // 0
注: 如果與別處相似,純屬巧合~
若有問(wèn)題或者錯(cuò)誤請(qǐng)?jiān)谙路搅粞浴?/p>