為學(xué)習(xí)<數(shù)據(jù)結(jié)構(gòu)與算法>做準(zhǔn)備,我們有必要梳理一下數(shù)組,因?yàn)槲覀冃枰鼇砟M各種數(shù)據(jù)結(jié)構(gòu),如棧,列表,隊(duì)列等。而實(shí)際上
JavaScript的數(shù)組要比很多其他語言的數(shù)組功能強(qiáng)大太多了,在java語言中,如果我們實(shí)現(xiàn)刪除第一個(gè)元素,就需要把所有后面的元素都向前挪一位,而在JavaScript中,只需要調(diào)用shift方法就可以了,而其他類似的方法還有很多,所以我們開始吧!
數(shù)組的length屬性
數(shù)組的length屬性非常有意思,它和數(shù)組下標(biāo)密不可分,它的取值范圍是0 到 2的32次方 = 4294967296 -1 的整數(shù).
所以如果我們設(shè)置它為負(fù)數(shù)或者大于4294967296-1就會(huì)報(bào)錯(cuò)。
var namelistA = new Array(4294967296); // 2的32次方 = 4294967296
var namelistC = new Array(-100) // 負(fù)號(hào)
console.log(namelistA.length); // RangeError: 無效數(shù)組長度
console.log(namelistC.length); // RangeError: 無效數(shù)組長度
數(shù)組的方法
Array.from() ---ie不支持
從一個(gè)類似數(shù)組或可迭代對象創(chuàng)建一個(gè)新的,淺拷貝的數(shù)組實(shí)例。例如:
Array.from('foo');
// [ "f", "o", "o" ]
const set = new Set(['foo', 'bar', 'baz', 'foo']);
Array.from(set);
// [ "foo", "bar", "baz" ]
Array.isArray() --- ie9支持
判斷是否是數(shù)組,這個(gè)方法要優(yōu)先于使用instanceOf,
因?yàn)?code>Array.isArray能檢測iframes
var iframe = document.createElement('iframe');
document.body.appendChild(iframe);
xArray = window.frames[window.frames.length-1].Array;
var arr = new xArray(1,2,3); // [1,2,3]
// Correctly checking for Array
Array.isArray(arr); // true
// Considered harmful, because doesn't work though iframes
arr instanceof Array; // false
如果沒有這個(gè)方法 Array.isArray(),我們可以添加全局方法:
if (!Array.isArray) {
Array.isArray = function(arg) {
return Object.prototype.toString.call(arg) === '[object Array]';
};
}
關(guān)于判斷數(shù)組是否是數(shù)組,可以看這篇文章
Array.of() 創(chuàng)建一個(gè)數(shù)組實(shí)例,而不考慮參數(shù)的類型和數(shù)量。
它和數(shù)組的構(gòu)造函數(shù)的區(qū)別就是關(guān)于對整數(shù)的處理,構(gòu)造函數(shù)Array(7)會(huì)創(chuàng)造一個(gè)有七個(gè)空元素的數(shù)組,而Array.of(7)會(huì)創(chuàng)建一個(gè)只有一個(gè)元素7的數(shù)組。
這個(gè)方法ie就不支持,所以可以添加如下方法來做兼容
if (!Array.of) {
Array.of = function() {
return Array.prototype.slice.call(arguments);
};
}
修改方法
我們把數(shù)組的方法分為修改方法和迭代方法,修改方法會(huì)把調(diào)用它的原生數(shù)組對象修改了,而迭代方法不會(huì)修改原生的對象。
copyWithin()
方法淺復(fù)制數(shù)組的一部分到同一數(shù)組中的另一個(gè)位置,并返回它,不會(huì)改變原數(shù)組的長度。就是調(diào)換數(shù)組中元素。
const array1 = ['a', 'b', 'c', 'd', 'e'];
// copy to index 0 the element at index 3
console.log(array1.copyWithin(0, 3, 4));
// expected output: Array ["d", "b", "c", "d", "e"]
// copy to index 1 all elements from index 3 to the end
console.log(array1.copyWithin(1, 3));
// expected output: Array ["d", "d", "e", "d", "e"]
fill()
填充方法,用一個(gè)固定值填充數(shù)組從索引起始位置到終止位置,但是不包括終止位置。
[1, 2, 3].fill(4); // [4, 4, 4]
[1, 2, 3].fill(4, 1); // [1, 4, 4]
[1, 2, 3].fill(4, 1, 2); // [1, 4, 3]
[1, 2, 3].fill(4, 1, 1); // [1, 2, 3]
[1, 2, 3].fill(4, 3, 3); // [1, 2, 3]
[1, 2, 3].fill(4, -3, -2); // [4, 2, 3]
[1, 2, 3].fill(4, NaN, NaN); // [1, 2, 3]
[1, 2, 3].fill(4, 3, 5); // [1, 2, 3]
Array(3).fill(4); // [4, 4, 4]
[].fill.call({ length: 3 }, 4); // {0: 4, 1: 4, 2: 4, length: 3}
這個(gè)方法會(huì)修改調(diào)用數(shù)組,而不是返回一個(gè)新的數(shù)組。
pop()
該方法刪除數(shù)組最后一個(gè)元素并返回,同時(shí)修改其length,也就是修改其原對象。
let myFish = ["angel", "clown", "mandarin", "surgeon"];
let popped = myFish.pop();
console.log(myFish);
// ["angel", "clown", "mandarin"]
console.log(popped);
// surgeon
pop 方法有意具有通用性。該方法和 call() 或 apply() 一起使用時(shí),可應(yīng)用在類似數(shù)組的對象上。pop方法根據(jù) length屬性來確定最后一個(gè)元素的位置。如果不包含length屬性或length屬性不能被轉(zhuǎn)成一個(gè)數(shù)值,會(huì)將length置為0,并返回undefined。
push()
和上一個(gè)方法相反,它在數(shù)組最后一個(gè)位置添加元素
var sports = ["soccer", "baseball"];
var total = sports.push("football", "swimming");
console.log(sports);
// ["soccer", "baseball", "football", "swimming"]
console.log(total);
// 4
reverse()
順序轉(zhuǎn)換方法,第一個(gè)變最后一個(gè),最后一個(gè)變第一個(gè)。
const a = [1, 2, 3];
console.log(a); // [1, 2, 3]
a.reverse();
console.log(a); // [3, 2, 1]
shift()
方法從數(shù)組中刪除第一個(gè)元素,并返回該元素的值。此方法更改數(shù)組的長度。
用這個(gè)方法我們可以模擬出棧,
const array1 = [1, 2, 3];
const firstElement = array1.shift();
console.log(array1);
// expected output: Array [2, 3]
console.log(firstElement);
// expected output: 1
shift 方法移除索引為 0 的元素(即第一個(gè)元素),并返回被移除的元素,其他元素的索引值隨之減 1。如果length 屬性的值為 0 (長度為 0),則返回undefined。
shift 方法并不局限于數(shù)組:這個(gè)方法能夠通過 call 或 apply 方法作用于類似數(shù)組的對象上。但是對于沒有length 屬性(從0開始的一系列連續(xù)的數(shù)字屬性的最后一個(gè))的對象,調(diào)用該方法可能沒有任何意義。
這個(gè)方法和pop方法相似。也是通用性的。
sort()
排序算法,如果不指定排序算法,那么元素會(huì)按照轉(zhuǎn)換為的字符串的諸個(gè)字符的Unicode位點(diǎn)進(jìn)行排序。例如 "Banana" 會(huì)被排列到 "cherry" 之前。當(dāng)數(shù)字按由小到大排序時(shí),9 出現(xiàn)在 80 之前,但因?yàn)椋]有指明 compareFunction),比較的數(shù)字會(huì)先被轉(zhuǎn)換為字符串,所以在Unicode順序上 "80" 要比 "9" 要靠前。
const months = ['March', 'Jan', 'Feb', 'Dec'];
months.sort();
console.log(months);
// expected output: Array ["Dec", "Feb", "Jan", "March"]
const array1 = [1, 30, 4, 21, 100000];
array1.sort();
console.log(array1);
// expected output: Array [1, 100000, 21, 30, 4]
排序算法我們可以寫成這樣:
function compare(a, b) {
if (a < b ) { // 按某種排序標(biāo)準(zhǔn)進(jìn)行比較, a 小于 b
return -1;
}
if (a > b ) {
return 1;
}
// a must be equal to b
return 0;
}
如果是數(shù)組的對象排序,我們可以這樣寫:
var items = [
{ name: 'Edward', value: 21 },
{ name: 'Sharpe', value: 37 },
{ name: 'And', value: 45 },
{ name: 'The', value: -12 },
{ name: 'Magnetic' },
{ name: 'Zeros', value: 37 }
];
// sort by value
items.sort(function (a, b) {
return (a.value - b.value)
});
這里就不展開了。
splice()
強(qiáng)大的splice方法。可攻可受。
該方法通過刪除或替換現(xiàn)有元素或者原地添加新的元素來修改數(shù)組,并以數(shù)組形式返回被修改的內(nèi)容。此方法會(huì)改變原數(shù)組。
它有三個(gè)參數(shù),start,deleteCount,item1,item2,item3
start:指定修改的起始位置,從0開始,如果超出數(shù)組長度,并不會(huì)報(bào)錯(cuò),而是從數(shù)組末尾開始添加;如果是負(fù)數(shù),則從末尾開始計(jì)算,-1就是length-1,如果負(fù)數(shù)的絕對值大于數(shù)組的長度,則從0開始。
deleteCount:可選,刪除元素的個(gè)數(shù),如果是0則表示不刪除,而必須添加一個(gè)元素。
- 如果該參數(shù)大于
start后的元素個(gè)數(shù),則表示刪除start后的所有元素,包括start位置的元素
item1,item2,item3...:可選,表示要添加進(jìn)數(shù)組的元素,如果不指定,則splice將只刪除元素。
我們知道了上面的三個(gè)參數(shù),splice方法就是三個(gè)參數(shù)的配合使用,它的返回值是刪除的元素組成的數(shù)組,如果沒有刪除就返回空數(shù)組。
模仿pop方法,刪除最后一個(gè)元素
const array = ["A","B","C"];
let element = array.splice(array.length-1,1);
console.log(element);//["C"]
console.log(array)//["A", "B"]
模仿push方法,在數(shù)組的后面添加一個(gè)元素
const array = ["A","B","C"];
let element = array.splice(array.length,0,"D");
console.log(element);//[]
console.log(array)//["A", "B","C","D"]
模仿unshift方法,在數(shù)組的開頭添加元素
const array = ["A","B","C"];
let element = array.splice(0,0,"D");
console.log(element);//[]
console.log(array)//["D",A", "B","C"]
模仿shift方法,刪除數(shù)組開頭的元素
const array = ["A","B","C"];
let element = array.splice(0,1);
console.log(element);//["A"]
console.log(array)//["B","C"]
最后刪除2位置以后的所有元素
const array = ["A","B","C"];
let element = array.splice(1);
console.log(element) //["B",""]
unshift()
在數(shù)組的首位插入元素
let arr = [4,5,6];
arr.unshift(1,2,3);
console.log(arr); // [1, 2, 3, 4, 5, 6]
以上的方法在調(diào)用時(shí)都會(huì)修改原數(shù)組對象。而下面的方法則絕對不會(huì)修改原數(shù)組對象,而是返回新的數(shù)組實(shí)例或者不做更改。
訪問方法:
concat()
連接方法,它可以把兩個(gè)數(shù)組連接為一個(gè)數(shù)組,并返回一個(gè)新的實(shí)例。
const array1 = ['a', 'b', 'c'];
const array2 = ['d', 'e', 'f'];
const array3 = array1.concat(array2);
console.log(array3);
// expected output: Array ["a", "b", "c", "d", "e", "f"]
concat方法創(chuàng)建一個(gè)新的數(shù)組,它由被調(diào)用的對象中的元素組成,每個(gè)參數(shù)的順序依次是該參數(shù)的元素(如果參數(shù)是數(shù)組)或參數(shù)本身(如果參數(shù)不是數(shù)組)。它不會(huì)遞歸到嵌套數(shù)組參數(shù)中。
concat方法不會(huì)改變原數(shù)組,或者是對象,而是進(jìn)行淺拷貝,如果是對象類型,只會(huì)引入對象的連接,如果是字符串或者其他的類型,則會(huì)進(jìn)行拷貝。
includes
這個(gè)方法用來判斷數(shù)組是否包含一個(gè)元素,返回true和false.
[1, 2, 3].includes(2); // true
[1, 2, 3].includes(4); // false
[1, 2, 3].includes(3, 3); // false
[1, 2, 3].includes(3, -1); // true
[1, 2, NaN].includes(NaN); // true
它還有另一個(gè)參數(shù),就是查找的起始位置,從什么地方開始查找。
var arr = ['a', 'b', 'c'];
arr.includes('c', 3); // false
arr.includes('c', 100); // false
如果查找的位置超出數(shù)組的長度,則不會(huì)進(jìn)行查找。
這個(gè)方法是一個(gè)新方法,ie不支持。
我們可以使用該方法來做一些去掉if語句的優(yōu)化。
join()
將一個(gè)數(shù)組(或一個(gè)類數(shù)組對象)的所有元素連接成一個(gè)字符串并返回這個(gè)字符串。如果數(shù)組只有一個(gè)項(xiàng)目,那么將返回該項(xiàng)目而不使用分隔符。
const elements = ['Fire', 'Air', 'Water'];
console.log(elements.join());
// expected output: "Fire,Air,Water"
console.log(elements.join(''));
// expected output: "FireAirWater"
console.log(elements.join('-'));
// expected output: "Fire-Air-Water"
指定一個(gè)字符串來分隔數(shù)組的每個(gè)元素。如果需要,將分隔符轉(zhuǎn)換為字符串。如果缺省該值,數(shù)組元素用逗號(hào)(,)分隔。如果separator是空字符串(""),則所有元素之間都沒有任何字符。
slice()
返回一個(gè)新的數(shù)組對象,這一對象是一個(gè)由begin 和end 決定的原數(shù)組的淺拷貝(包括 begin,不包括end)。原始數(shù)組不會(huì)被改變。
const animals = ['ant', 'bison', 'camel', 'duck', 'elephant'];
console.log(animals.slice(2));
// expected output: Array ["camel", "duck", "elephant"]
console.log(animals.slice(2, 4));
// expected output: Array ["camel", "duck"]
console.log(animals.slice(1, 5));
// expected output: Array ["bison", "camel", "duck", "elephant"]
start:可選,如果省略,則從0開始,如果是負(fù)數(shù),則從數(shù)組的后面開始計(jì)算。如果大于數(shù)組的長度,則返回空數(shù)組,
end:可選,如果省略,則拷貝到數(shù)組的末尾,如果是負(fù)數(shù),則從數(shù)組的后面開始計(jì)算,如果大于數(shù)組的長度,則返回?cái)?shù)組的最后末尾。
slice:方法會(huì)返回一個(gè)新的數(shù)組對象,進(jìn)行淺拷貝,對象元素是拷貝對象的引用,如果是字符串,整數(shù),布爾值則進(jìn)行拷貝。淺拷貝對象,則會(huì)造成修改對象,原對象也會(huì)修改。
const array = ["A","B","C"];
let data = array.slice();
console.log(data) // ["A","B","C"];
直接復(fù)制一個(gè)數(shù)組,返回一個(gè)新的。
indexOf()
這個(gè)方法和字符串的indexOf一樣,我一直以為只有字符串才有這個(gè)方法。它的作用是查找數(shù)組中元素的位置,如果存在就返回索引,如果沒有找到就返回-1.
var 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); // 0
那么如何找出數(shù)組中所有該元素的位置呢?
var indices = [];
var array = ['a', 'b', 'a', 'c', 'a', 'd'];
var element = 'a';
var idx = array.indexOf(element);
while (idx != -1) {
indices.push(idx);
idx = array.indexOf(element, idx + 1);
}
console.log(indices);
// [0, 2, 4]
lastIndexOf()
這個(gè)方法和上面indexOf作用一樣,只是從數(shù)組的末尾位置開始查找。
const animals = ['Dodo', 'Tiger', 'Penguin', 'Dodo'];
console.log(animals.lastIndexOf('Dodo'));
// expected output: 3
console.log(animals.lastIndexOf('Tiger'));
// expected output: 1
迭代方法
終于到了迭代方法,這里。
迭代方法他們都需要一個(gè)回調(diào)函數(shù),在遍歷每一個(gè)元素時(shí),把該元素放入回調(diào)函數(shù)中,進(jìn)行執(zhí)行操作。在這個(gè)遍歷的過程中,它會(huì)把length屬性緩沖到某個(gè)地方,在遍歷的時(shí)候,如果你在遍歷的過程中添加了新的元素,后面的遍歷并不會(huì)被遍歷到。而如果你刪除了某個(gè)元素,則有可能造成未知的影響。所以在遍歷的時(shí)候不要對原數(shù)組對象進(jìn)行任何修改操作。
forEach()
我們熟悉的forEach,它的作用和map很像,區(qū)別是map會(huì)返回一個(gè)數(shù)組,而forEach則返回undefined,所以它無法鏈?zhǔn)秸{(diào)用。我們這里就說一下它的一些特性吧。
1.除了拋出錯(cuò)誤,你沒有任何辦法來終止或者跳出循環(huán)遍歷,如果你想要中途跳出循環(huán),請換一種實(shí)現(xiàn)方式,例如:
- 一個(gè)簡單的 for 循環(huán)
- for...of / for...in 循環(huán)
- Array.prototype.every()
- Array.prototype.some()
- Array.prototype.find()
- Array.prototype.findIndex()
2.它只可以對有效值進(jìn)行遍歷
什么叫有效值,一個(gè)數(shù)組是這樣const arr = [1,,3,7],那么它的有效值就是1,3,7而中間的那個(gè)值就不會(huì)被遍歷到而是跳過。
const arraySparse = [1,3,,7];
let numCallbackRuns = 0;
arraySparse.forEach(function(element){
console.log(element);
numCallbackRuns++;
});
console.log("numCallbackRuns: ", numCallbackRuns);
// 1
// 3
// 7
// numCallbackRuns: 3
3.它不可以鏈?zhǔn)秸{(diào)用
因?yàn)樗恳淮螆?zhí)行完畢回調(diào)函數(shù),返回的是undefined,它無法向map,reduce那樣。
4.它在調(diào)用時(shí)不會(huì)改變原數(shù)組,準(zhǔn)確的說是,它不改變原數(shù)組,但是保不齊它的回調(diào)函數(shù)會(huì)改變。
entries()方法
該方法返回一個(gè)新的Array Iterator對象,該對象包含數(shù)組中每個(gè)索引的鍵/值對。
關(guān)于它的使用這里就不在描述,可以看一個(gè)比較復(fù)雜的例子:
function sortArr(arr) {
var goNext = true;
var entries = arr.entries();
while (goNext) {
var result = entries.next();
if (result.done !== true) {
result.value[1].sort((a, b) => a - b);
goNext = true;
} else {
goNext = false;
}
}
return arr;
}
var arr = [[1,34],[456,2,3,44,234],[4567,1,4,5,6],[34,78,23,1]];
sortArr(arr);
/*(4) [Array(2), Array(5), Array(5), Array(4)]
0:(2) [1, 34]
1:(5) [2, 3, 44, 234, 456]
2:(5) [1, 4, 5, 6, 4567]
3:(4) [1, 23, 34, 78]
length:4
__proto__:Array(0)
*/
every()方法
該方法測試一個(gè)數(shù)組內(nèi)的所有元素是否都能通過某個(gè)指定函數(shù)的測試。它返回一個(gè)布爾值。
用人話說就是,檢查所有人,是不是大于30歲?
需要注意的是,調(diào)用這個(gè)方法的數(shù)組是空數(shù)組,則永遠(yuǎn)返回true
const isBelowThreshold = (currentValue) => currentValue < 40;
const array1 = [1, 30, 39, 29, 10, 13];
console.log(array1.every(isBelowThreshold));
// expected output: true
我們有必要聽一下它的描述:
every 方法為數(shù)組中的每個(gè)元素執(zhí)行一次 callback 函數(shù),直到它找到一個(gè)會(huì)使 callback 返回 false 的元素。如果發(fā)現(xiàn)了一個(gè)這樣的元素,every方法將會(huì)立即返回 false。否則,callback 為每一個(gè)元素返回 true,every 就會(huì)返回 true。callback 只會(huì)為那些已經(jīng)被賦值的索引調(diào)用。不會(huì)為那些被刪除或從未被賦值的索引調(diào)用。
callback 在被調(diào)用時(shí)可傳入三個(gè)參數(shù):元素值,元素的索引,原數(shù)組。
如果為 every 提供一個(gè) thisArg 參數(shù),則該參數(shù)為調(diào)用 callback 時(shí)的 this 值。如果省略該參數(shù),則 callback 被調(diào)用時(shí)的 this 值,在非嚴(yán)格模式下為全局對象,在嚴(yán)格模式下傳入 undefined。詳見 this 條目。
every 不會(huì)改變原數(shù)組。
every 遍歷的元素范圍在第一次調(diào)用 callback 之前就已確定了。在調(diào)用 every 之后添加到數(shù)組中的元素不會(huì)被 callback 訪問到。如果數(shù)組中存在的元素被更改,則他們傳入 callback 的值是 every 訪問到他們那一刻的值。那些被刪除的元素或從來未被賦值的元素將不會(huì)被訪問到。
every 和數(shù)學(xué)中的"所有"類似,當(dāng)所有的元素都符合條件才會(huì)返回true。正因如此,若傳入一個(gè)空數(shù)組,無論如何都會(huì)返回 true。(這種情況屬于無條件正確:正因?yàn)橐粋€(gè)空集合沒有元素,所以它其中的所有元素都符合給定的條件。)
使用箭頭函數(shù):
[12, 5, 8, 130, 44].every(x => x >= 10); // false
[12, 54, 18, 130, 44].every(x => x >= 10); // true
some() 方法
該方法測試數(shù)組中是不是至少有1個(gè)元素通過了被提供的函數(shù)測試。它返回的是一個(gè)Boolean類型的值。
它和上面every()方法都是用來判斷數(shù)組中的元素符合一個(gè)給定的條件。區(qū)別是every是判斷所有的元素全都符合才返回true,只要一個(gè)不符合就返回false,而some是只要有一個(gè)元素符合就返回true.
需要注意的是:如果用一個(gè)空數(shù)組進(jìn)行測試,在任何情況下它返回的都是false。
看一下例子:數(shù)組中是否有大于10的元素存在。
function isBiggerThan10(element, index, array) {
return element > 10;
}
[2, 5, 8, 1, 4].some(isBiggerThan10); // false
[12, 5, 8, 1, 4].some(isBiggerThan10); // true
filter()方法
該方法創(chuàng)建一個(gè)新數(shù)組, 其包含通過所提供函數(shù)實(shí)現(xiàn)的測試的所有元素。
const words = ['spray', 'limit', 'elite', 'exuberant', 'destruction', 'present'];
const result = words.filter(word => word.length > 6);
console.log(result);
// expected output: Array ["exuberant", "destruction", "present"]
通過一個(gè)給定的條件來篩選符合的元素并返回一個(gè)新的數(shù)組。所以我們可以通過這個(gè)filter方法來實(shí)現(xiàn)一個(gè)remove的操作,原理非常簡單,篩選不是這個(gè)元素的元素并返回,就相當(dāng)于刪除了它了。
const arr = [1,2,3,4,5,6];
const after_arr = arr.filter(item=>item !== 3);
console.loog(arrter_arr);
//[1,2,4,5,6]
find()方法
找到符合給定條件的第一個(gè)元素,并返回,否則返回undefined.
const array1 = [5, 12, 8, 130, 44];
const found = array1.find(element => element > 10);
console.log(found);
// expected output: 12
這個(gè)方法有一個(gè)特殊的點(diǎn):那就是對[1,2,3,,5,6]這種數(shù)組,它并不是遍歷有效值,而是從0 ~ length-1,也就是中間那個(gè)沒有值的位置也會(huì)遍歷到,那么這樣的話就沒有forEach這種只遍歷有效值的方法有效率。
findIndex()方法
該方法和上面的方法很像,區(qū)別是這個(gè)方法返回索引,而上面的方法則返回元素。
const array1 = [5, 12, 8, 130, 44];
const isLargeNumber = (element) => element > 13;
console.log(array1.findIndex(isLargeNumber));
// expected output: 3
keys()方法
該方法返回一個(gè)包含數(shù)組中每個(gè)索引鍵的Array Iterator對象。
它特殊的地方是會(huì)返回沒有對應(yīng)元素的索引。
var arr = ["a", , "c"];
var sparseKeys = Object.keys(arr);
var denseKeys = [...arr.keys()];
console.log(sparseKeys); // ['0', '2']
console.log(denseKeys); // [0, 1, 2]
map()方法
我們最最常用的方法。該方法創(chuàng)建一個(gè)新數(shù)組,其結(jié)果是該數(shù)組中的每個(gè)元素都調(diào)用一個(gè)提供的函數(shù)后返回的結(jié)果。
const array1 = [1, 4, 9, 16];
// pass a function to map
const map1 = array1.map(x => x * 2);
console.log(map1);
// expected output: Array [2, 8, 18, 32]
map 方法會(huì)給原數(shù)組中的每個(gè)元素都按順序調(diào)用一次 callback 函數(shù)。callback 每次執(zhí)行后的返回值(包括 undefined)組合起來形成一個(gè)新數(shù)組。 callback 函數(shù)只會(huì)在有值的索引上被調(diào)用;那些從來沒被賦過值或者使用delete 刪除的索引則不會(huì)被調(diào)用。
如果你不打算用map返回的新數(shù)組,那么你就不要用這個(gè)方法,這樣會(huì)很讓人疑惑,你可以使用forEach或者for ... of等其他的方法來代替.
下面的例子演示如何在一個(gè) String 上使用 map 方法獲取字符串中每個(gè)字符所對應(yīng)的 ASCII 碼組成的數(shù)組:
var map = Array.prototype.map
var a = map.call("Hello World", function(x) {
return x.charCodeAt(0);
})
// a的值為[72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100]
更多的map信息可以來MDN查詢閱讀。
reduce()方法
該方法對數(shù)組中的每個(gè)元素執(zhí)行一個(gè)由您提供的reducer函數(shù)(升序執(zhí)行),將其結(jié)果匯總為單個(gè)返回值。
const array1 = [1, 2, 3, 4];
const reducer = (accumulator, currentValue) => accumulator + currentValue;
// 1 + 2 + 3 + 4
console.log(array1.reduce(reducer));
// expected output: 10
// 5 + 1 + 2 + 3 + 4
console.log(array1.reduce(reducer, 5));
// expected output: 15
reducer 函數(shù)接收4個(gè)參數(shù):
- Accumulator (acc) (累計(jì)器)
- Current Value (cur) (當(dāng)前值)
- Current Index (idx) (當(dāng)前索引)
- Source Array (src) (源數(shù)組)
reducer 函數(shù)的返回值分配給累計(jì)器,該返回值在數(shù)組的每個(gè)迭代中被記住,并最后成為最終的單個(gè)結(jié)果值。
reduce為數(shù)組中的每一個(gè)元素依次執(zhí)行callback函數(shù),不包括數(shù)組中被刪除或從未被賦值的元素,接受四個(gè)參數(shù):
accumulator 累計(jì)器
currentValue 當(dāng)前值
currentIndex 當(dāng)前索引
array 數(shù)組
回調(diào)函數(shù)第一次執(zhí)行時(shí),accumulator 和currentValue的取值有兩種情況:如果調(diào)用reduce()時(shí)提供了initialValue,accumulator取值為initialValue,currentValue取數(shù)組中的第一個(gè)值;如果沒有提供 initialValue,那么accumulator取數(shù)組中的第一個(gè)值,`currentValue``取數(shù)組中的第二個(gè)值。
注意:如果沒有提供initialValue,reduce 會(huì)從索引1的地方開始執(zhí)行 callback 方法,跳過第一個(gè)索引。如果提供initialValue,從索引0開始。
如果數(shù)組為空且沒有提供initialValue,會(huì)拋出TypeError 。如果數(shù)組僅有一個(gè)元素(無論位置如何)并且沒有提供initialValue, 或者有提供initialValue但是數(shù)組為空,那么此唯一值將被返回并且callback不會(huì)被執(zhí)行。
提供初始值通常更安全,正如下面的例子,如果沒有提供initialValue,則可能有三種輸出:
var maxCallback = ( acc, cur ) => Math.max( acc.x, cur.x );
var maxCallback2 = ( max, cur ) => Math.max( max, cur );
// reduce() 沒有初始值
[ { x: 22 }, { x: 42 } ].reduce( maxCallback ); // 42
[ { x: 22 } ].reduce( maxCallback ); // { x: 22 }
[ ].reduce( maxCallback ); // TypeError
// map/reduce; 這是更好的方案,即使傳入空數(shù)組或更大數(shù)組也可正常執(zhí)行
[ { x: 22 }, { x: 42 } ].map( el => el.x )
.reduce( maxCallback2, -Infinity );
關(guān)于reduce和reduceRight方法的更多信息,可以看MDN官網(wǎng)的文章。。
關(guān)于數(shù)組的學(xué)習(xí)就到這里把。
over...