本文是 重溫基礎 系列文章的第十篇。
今日感受:平安夜,多棒。
系列目錄:
- 【複習資料】ES6/ES7/ES8/ES9資料整理(個人整理)
- 【重溫基礎】1.語法和資料型別
- 【重溫基礎】2.流程控制和錯誤處理
- 【重溫基礎】3.迴圈和迭代
- 【重溫基礎】4.函式
- 【重溫基礎】5.表示式和運算子
- 【重溫基礎】6.數字
- 【重溫基礎】7.時間物件
- 【重溫基礎】8.字串
- 【重溫基礎】9.正規表示式
本章節複習的是JS中的陣列,以索引進行排序。
前置知識:
陣列是一個有序的資料集合,使用陣列名稱和索引進行訪問。
let arr = [1,2,3];
arr[0] = 1;
複製程式碼
在JavaScript中陣列沒有明確資料型別。
let arr = [1, 'hi', undefined, fun()];
複製程式碼
1.建立陣列
建立陣列方法有3種:
let arr = new Array(ele1, ele2, ele3, ..., eleN);
let arr = Array(ele1, ele2, ele3, ..., eleN);
let arr = [ele1, ele2, ele3, ..., eleN];
複製程式碼
上面是已知陣列元素,另外一種還有建立一個長度不為0,且有沒有任何元素的陣列:
let len = 5;
let arr = new Array(len); // 方法1
let arr = Array(len); // 方法2
let arr = []; // 方法3
arr.length = len;
複製程式碼
若傳入的陣列長度不是整數,則報錯:
let arr = new Array(3.5);
let arr = Array(3.5);
let arr = [];
arr.length = 3.5;
//Uncaught RangeError: Invalid array length
複製程式碼
其中要注意這兩種建立方法是不同的:
let arr1 = new Array(4); // [empty × 4]
let arr2 = [4]; // [4]
for(let k in arr1){
console.log(k);
} // undefined
for(let k in arr2){
console.log(k);
} // 0
複製程式碼
2.使用陣列
2.1 簡單使用
獲取陣列指定位置的值:
let a = [1,2,5];
a[0]; // 1
a[2]; // 5
a[3]; // undefined
複製程式碼
獲取陣列長度:
let a = [1,2,5];
a.length; // 3
a["length"]; // 3
複製程式碼
設定陣列指定位置的值:
let a = [1,2,5];
a[0] = 9;
a[2] = 99;
a[3] = 999;
複製程式碼
2.2 理解陣列length
- 陣列的索引值是從
0
開始,即上面陣列索引0
的是1
,索引1
的值是2
,依次下去。 - 陣列
length
永遠返回的是陣列最後一個元素的索引加1。 - 可通過
arr.length = 0
來清空陣列。 - 可通過
arr.length = len
來設定陣列長度。
2.3 遍歷陣列
遍歷陣列就是以某種方法處理陣列的每個元素,簡單如下:
- 使用
for
迴圈:
let arr = ["pingan", "leo", "robin"];
for (let i = 0; i<arr.length; i++){
// 處理元素的操作
console.log(`第${i}個元素是:${arr[i]};`)
}
// 第0個元素是:pingan;
// 第1個元素是:leo;
// 第2個元素是:robin;
複製程式碼
- 使用
for...in
:
let arr = ["pingan", "leo", "robin"];
for(let i in arr){
console.log(`第${i}個元素是:${arr[i]};`)
}
// 第0個元素是:pingan;
// 第1個元素是:leo;
// 第2個元素是:robin;
複製程式碼
- 使用
forEach
:
arr.forEach(callback)
接收一個回撥方法。
callback(val, index, array)
: 接收三個引數:val
: 當前處理的元素;index
: 當前處理的元素的索引;array
: 正在處理的陣列;
可參考MDN Array.prototype.forEach 的詳細介紹。
let arr = ["pingan", "leo", "robin"];
arr.forEach(function(val, i, array){
console.log(`第${i}個元素是:${val};`)
})
複製程式碼
3. 陣列方法(訪問和修改)
方法名稱 | 方法介紹 |
---|---|
concat() |
連線兩個或更多的陣列,並返回結果。 |
join() |
把陣列的所有元素放入一個字串。元素通過指定的分隔符進行分隔。 |
pop() |
刪除並返回陣列的最後一個元素 |
push() |
向陣列的末尾新增一個或更多元素,並返回新的長度。 |
reverse() |
顛倒陣列中元素的順序。 |
shift() |
刪除並返回陣列的第一個元素 |
slice() |
從某個已有的陣列返回選定的元素 |
sort() |
對陣列的元素進行排序 |
splice() |
刪除元素,並向陣列新增新元素。 |
toSource() |
返回該物件的原始碼。 |
toString() |
把陣列轉換為字串,並返回結果。 |
toLocaleString() |
把陣列轉換為本地陣列,並返回結果。 |
unshift() |
向陣列的開頭新增一個或更多元素,並返回新的長度。 |
valueOf() |
返回陣列物件的原始值 |
indexOf() |
在陣列中搜尋指定元素並返回第一個匹配的索引 |
lastIndexOf() |
在陣列中搜尋指定元素並返回最後一個匹配的索引 |
可參考W3school JavaScript Array 物件 的詳細介紹。
3.1 concat()
連線兩個或更多的陣列,並返回一個新陣列。
- 語法:
arr.concat(a1, a2, ..., an)
; - 引數:
arr
:目標陣列;
a1,a2,...,an
:需要合併的元素;
let a1 = [1,2,3];
let a2 = [9,99,999];
let a = a1.concat(a2);
// [1, 2, 3, 9, 99, 999]
複製程式碼
3.2 join()
使用指定分隔符,連線兩個或多個陣列的元素,返回一個字串。
- 語法:
arr.join(sep)
; - 引數:
arr
:目標陣列;
sep
:連線的分隔符,預設值為“,
”;
let arr = ["pingan", "leo", "robin"];
arr.join(); // "pingan,leo,robin"
arr.join(""); // "pinganleorobin"
arr.join(","); // "pingan,leo,robin"
複製程式碼
3.3 pop()和push()
-
pop()
: 刪除並返回陣列最後一個元素,改變原陣列。 -
push(item)
: 向陣列末尾新增一個或多個元素,改變原陣列,返回新的陣列長度。
方便記憶和理解:兩個都是從陣列末尾操作,pop()
是刪除最後一個元素,push()
是向最後一位新增新的元素。
let arr = ["pingan", "leo"];
let a1 = arr.pop(); // "leo"
let a2 = arr.push("robin","hi"); // 3
arr; // ["pingan", "robin", "hi"]
複製程式碼
3.4 shift()和unshift()
shift()
: 刪除並返回陣列第一個元素,改變原陣列。unshift(item)
: 向陣列頭部新增一個或多個元素,改變原陣列,返回新的陣列長度。
方便記憶和理解:兩個都是從陣列頭部操作,shift()
是刪除第一個元素,unshift()
是向第一位新增新的元素。
let arr = ["pingan", "leo"];
let a1 = arr.shift(); // "pingan"
let a2 = arr.unshift("robin","hi"); // 3
arr; // ["robin", "hi", "leo"]
複製程式碼
3.5 reverse()
顛倒陣列中元素的順序,改變原陣列。
let arr = [1, 2, 3, 4];
arr.reverse(); // [4, 3, 2, 1]
複製程式碼
3.6 slice()
用於提取陣列中一個片段,作為新陣列返回。
slice(start[,end])
: 接收2個引數:
start
: 必需,指定起始索引,若負數則從陣列最後開始算起,-1
為倒數第一位,-2
為倒數第二位,以此類推。end
: 可選,指定結束索引,若沒傳則表示到陣列結束。
注意:
end
若有指定的話,是不包含end
索引上的值。
let arr = [1, 2, 3, 5, 6];
let a1 = arr.slice(2); // [3, 5, 6]
let a2 = arr.slice(2,3); // [3]
複製程式碼
3.7 splice()
從陣列中刪除指定索引開始的專案,然後返回被刪除的專案。
- 語法:
arr.splice(index, num, a1, a2,...,an)
; - 引數:
index
: 必需,起始位置的索引,若負數則從陣列最後開始算起;
num
:必需,刪除的數量,若為0則不刪除;
a1,a2,...an
:可選,為陣列新增的元素;
let arr = [1, 2, 3, 4];
let a = arr.splice(1, 2, "hi", "leo");
// a => [2, 3]
// arr => [1, "hi", "leo", 4]
複製程式碼
3.8 sort()
對陣列的元素進行排序,改變原陣列。
可接受一個回撥方法作為比較函式,來決定排序方式。
比較函式應該具有兩個引數 a
和 b
,返回值如下:
若 a
小於 b
,在排序後的陣列中 a 應該出現在 b 之前,則返回一個小於 0 的值。
若 a
等於 b
,則返回 0。
若 a
大於 b
,則返回一個大於 0 的值。
let a1 = [1,3,6,9,10];
a1.sort(); // [1, 10, 3, 6, 9]
a1.sort(function(a,b){
return a > b ? 1 : a < b ? -1 : 0;
}) // [1, 3, 6, 9, 10]
複製程式碼
3.9 indexOf()和lastIndexOf()
兩者都是在陣列搜尋指定元素,只是indexOf()
返回的是搜尋到的第一個元素的索引,而lastIndexOf()
返回的是搜尋到的最後一個元素的索引。
語法:
indexOf(ele[,start])
和lastIndexOf(ele[,start])
;
引數:
ele
: 需要搜尋的元素。start
: 開始搜尋的索引。
let arr = ["hh1", "hh2", "hh2", "hh2", "hh3", "hh4"];
let a1 = arr.indexOf("hh2"); // 1
let a2 = arr.lastIndexOf("hh2"); // 3
let a3 = arr.indexOf("hh2",2); // 2
複製程式碼
4. 陣列方法(迭代)
方法名稱 | 方法介紹 |
---|---|
forEach() |
為陣列中的每個元素執行一次回撥函式。 |
every() |
如果陣列中的每個元素都滿足測試函式,則返回 true,否則返回 false。 |
some() |
如果陣列中至少有一個元素滿足測試函式,則返回 true,否則返回 false。 |
filter() |
將所有在過濾函式中返回 true 的陣列元素放進一個新陣列中並返回。 |
map() |
返回一個由回撥函式的返回值組成的新陣列。 |
reduce() |
從左到右為每個陣列元素執行一次回撥函式,並把上次回撥函式的返回值放在一個暫存器中傳給下次回撥函式,並返回最後一次回撥函式的返回值。 |
reduceRight() |
從右到左為每個陣列元素執行一次回撥函式,並把上次回撥函式的返回值放在一個暫存器中傳給下次回撥函式,並返回最後一次回撥函式的返回值。 |
以下是ES6規範新增的陣列方法:
方法名稱 | 方法介紹 |
---|---|
keys() |
返回一個陣列迭代器物件,該迭代器會包含所有陣列元素的鍵。 |
values() |
返回一個陣列迭代器物件,該迭代器會包含所有陣列元素的值。 |
entries() |
返回一個陣列迭代器物件,該迭代器會包含所有陣列元素的鍵值對。 |
find() |
找到第一個滿足測試函式的元素並返回那個元素的值,如果找不到,則返回 undefined。 |
findIndex() |
找到第一個滿足測試函式的元素並返回那個元素的索引,如果找不到,則返回 -1。 |
可參考MDN Array 的詳細介紹。
4.1 forEach()
對陣列的每個元素執行一次提供的函式。
語法:
arr.forEach(callback)
。
引數:
callback(val, index, arr)
: 需要執行的函式,接收三個引數:
val
: 正在處理的當前元素;index
: 可選,正在處理的當前元素的索引;arr
: 可選,正在操作的陣列;
let a = [1,3,5,7];
a.forEach(function(val, index, arr){
arr[index] = val * 2
})
a ; // [2, 6, 10, 14]
複製程式碼
4.2 every()
測試陣列的所有元素是否都通過了指定函式的測試。
語法:
arr.every(callback)
。
引數:
callback(val, index, arr)
: 需要執行的函式,接收三個引數:
val
: 正在處理的當前元素;index
: 可選,正在處理的當前元素的索引;arr
: 可選,正在操作的陣列;
返回值:
若都通過返回true
,否則返回false
。
let a = [1, "", "aa", 13, 6];
let res = a.every(function(val, index, arr){
return typeof val == "number";
})
res;// false
let b = [1, 2, 3];
let r = b.every(function(val, index, arr){
return typeof val == "number";
})
r; // true
複製程式碼
4.3 some()
測試陣列中的某些元素是否通過由提供的函式實現的測試。
語法:
arr.some(callback)
。
引數:
callback(val, index, arr)
: 需要執行的函式,接收三個引數:
val
: 正在處理的當前元素;index
: 可選,正在處理的當前元素的索引;arr
: 可選,正在操作的陣列;
返回值:
若有一個通過返回true
,否則返回false
。
let a = [1, "", "aa", 13, 6];
let res = a.some(function(val, index, arr){
return typeof val == "number";
})
res;// true
let b = [1, 2, 3];
let r = b.some(function(val, index, arr){
return typeof val == "number";
})
r; // true
複製程式碼
4.4 filter()
將所有在過濾函式中返回 true
的陣列元素放進一個新陣列中並返回。
語法:
arr.filter(callback)
。
引數:
callback(val, index, arr)
: 需要執行的函式,接收三個引數:
val
: 正在處理的當前元素;index
: 可選,正在處理的當前元素的索引;arr
: 可選,正在操作的陣列;
返回值:
一個返回通過測試的元素的陣列,若都沒有則返回空陣列。
let a = [1, "", "aa", 13, 6];
let res = a.filter(function(val, index, arr){
return typeof val == "number";
})
res;//[1, 13, 6]
複製程式碼
4.5 map()
傳入一個操作函式,對每個元素執行此方法,並返回一個執行後的陣列。
語法:
arr.map(callback)
。
引數:
callback(val, index, arr)
: 需要執行的函式,接收三個引數:
val
: 正在處理的當前元素;index
: 可選,正在處理的當前元素的索引;arr
: 可選,正在操作的陣列;
返回值:
一個新陣列,每個元素都是回撥函式的結果。
let a = [1, 3, 5];
let b = a.map(function(val, index, arr){
return val + 2;
})
b; //[3, 5, 7]
複製程式碼
5. 陣列的擴充(ES6)
5.1 擴充運算子
擴充運算子使用(...
),類似rest
引數的逆運算,將陣列轉為用(,
)分隔的引數序列。
console.log(...[1, 2, 3]); // 1 2 3
console.log(1, ...[2,3], 4); // 1 2 3 4
複製程式碼
擴充運算子主要使用在函式呼叫。
function f (a, b){
console.log(a, b);
}
f(...[1, 2]); // 1 2
function g (a, b, c, d, e){
console.log(a, b, c, d, e);
}
g(0, ...[1, 2], 3, ...[4]); // 0 1 2 3 4
複製程式碼
若擴充運算子後面是個空陣列,則不產生效果。
[...[], 1]; // [1]
複製程式碼
替代apply方法
// ES6之前
function f(a, b, c){...};
var a = [1, 2, 3];
f.apply(null, a);
// ES6之後
function f(a, b, c){...};
let a = [1, 2, 3];
f(...a);
// ES6之前
Math.max.apply(null, [3,2,6]);
// ES6之後
Math.max(...[3,2,6]);
複製程式碼
擴充運算子的運用
- (1)複製陣列:
通常我們直接複製陣列時,只是淺拷貝,如果要實現深拷貝,可以使用擴充運算子。
// 通常情況 淺拷貝
let a1 = [1, 2];
let a2 = a1;
a2[0] = 3;
console.log(a1,a2); // [3,2] [3,2]
// 擴充運算子 深拷貝
let a1 = [1, 2];
let a2 = [...a1];
// let [...a2] = a1; // 作用相同
a2[0] = 3;
console.log(a1,a2); // [1,2] [3,2]
複製程式碼
- (2)合併陣列:
注意,這裡合併陣列,只是淺拷貝。
let a1 = [1,2];
let a2 = [3];
let a3 = [4,5];
// ES5
let a4 = a1.concat(a2, a3);
// ES6
let a5 = [...a1, ...a2, ...a3];
a4[0] === a1[0]; // true
a5[0] === a1[0]; // true
複製程式碼
- (3)與解構賦值結合:
與解構賦值結合生成陣列,但是使用擴充運算子需要放到引數最後一個,否則報錯。
let [a, ...b] = [1, 2, 3, 4];
// a => 1 b => [2,3,4]
let [a, ...b] = [];
// a => undefined b => []
let [a, ...b] = ["abc"];
// a => "abc" b => []
複製程式碼
5.2 Array.from()
將 類陣列物件 和 可遍歷的物件,轉換成真正的陣列。
// 類陣列物件
let a = {
'0':'a',
'1':'b',
length:2
}
let arr = Array.from(a);
// 可遍歷的物件
let a = Array.from([1,2,3]);
let b = Array.from({length: 3});
let c = Array.from([1,2,3]).map(x => x * x);
let d = Array.from([1,2,3].map(x => x * x));
複製程式碼
5.3 Array.of()
將一組數值,轉換成陣列,彌補Array
方法引數不同導致的差異。
Array.of(1,2,3); // [1,2,3]
Array.of(1).length; // 1
Array(); // []
Array(2); // [,] 1個引數時,為指定陣列長度
Array(1,2,3); // [1,2,3] 多於2個引數,組成新陣列
複製程式碼
5.4 find()和findIndex()
find()
方法用於找出第一個符合條件的陣列成員,引數為一個回撥函式,所有成員依次執行該回撥函式,返回第一個返回值為true
的成員,如果沒有一個符合則返回undefined
。
[1,2,3,4,5].find( a => a < 3 ); // 1
複製程式碼
回撥函式接收三個引數,當前值、當前位置和原陣列。
[1,2,3,4,5].find((value, index, arr) => {
// ...
});
複製程式碼
findIndex()
方法與find()
類似,返回第一個符合條件的陣列成員的位置,如果都不符合則返回-1
。
[1,2,3,4].findIndex((v,i,a)=>{
return v>2;
}); // 2
複製程式碼
5.5 fill()
用於用指定值填充一個陣列,通常用來初始化空陣列,並抹去陣列中已有的元素。
new Array(3).fill('a'); // ['a','a','a']
[1,2,3].fill('a'); // ['a','a','a']
複製程式碼
並且fill()
的第二個和第三個引數指定填充的起始位置和結束位置。
[1,2,3].fill('a',1,2);// [1, "a", 3]
複製程式碼
5.6 entries(),keys(),values()
主要用於遍歷陣列,entries()
對鍵值對遍歷,keys()
對鍵名遍歷,values()
對鍵值遍歷。
for (let i of ['a', 'b'].keys()){
console.log(i)
}
// 0
// 1
for (let e of ['a', 'b'].values()){
console.log(e)
}
// 'a'
// 'b'
for (let e of ['a', 'b'].entries()){
console.log(e)
}
// 0 'a'
// 1 'b'
複製程式碼
5.7 includes()
用於表示陣列是否包含給定的值,與字串的includes
方法類似。
[1,2,3].includes(2); // true
[1,2,3].includes(4); // false
[1,2,NaN].includes(NaN); // true
複製程式碼
第二個引數為起始位置,預設為0
,如果負數,則表示倒數的位置,如果大於陣列長度,則重置為0
開始。
[1,2,3].includes(3,3); // false
[1,2,3].includes(3,4); // false
[1,2,3].includes(3,-1); // true
[1,2,3].includes(3,-4); // true
複製程式碼
5.8 flat(),flatMap()
flat()
用於將陣列一維化,返回一個新陣列,不影響原陣列。
預設一次只一維化一層陣列,若需多層,則傳入一個整數引數指定層數。
若要一維化所有層的陣列,則傳入Infinity
作為引數。
[1, 2, [2,3]].flat(); // [1,2,2,3]
[1,2,[3,[4,[5,6]]]].flat(3); // [1,2,3,4,5,6]
[1,2,[3,[4,[5,6]]]].flat('Infinity'); // [1,2,3,4,5,6]
複製程式碼
flatMap()
是將原陣列每個物件先執行一個函式,在對返回值組成的陣列執行flat()
方法,返回一個新陣列,不改變原陣列。
flatMap()
只能展開一層。
[2, 3, 4].flatMap((x) => [x, x * 2]);
// [2, 4, 3, 6, 4, 8]
複製程式碼
6. 陣列的擴充(ES7)
6.1 Array.prototype.includes()方法
includes()
用於查詢一個值是否在陣列中,如果在返回true
,否則返回false
。
['a', 'b', 'c'].includes('a'); // true
['a', 'b', 'c'].includes('d'); // false
複製程式碼
includes()
方法接收兩個引數,搜尋的內容和開始搜尋的索引,預設值為0,若搜尋值在陣列中則返回true
否則返回false
。
['a', 'b', 'c', 'd'].includes('b'); // true
['a', 'b', 'c', 'd'].includes('b', 1); // true
['a', 'b', 'c', 'd'].includes('b', 2); // false
複製程式碼
與indexOf
方法對比,下面方法效果相同:
['a', 'b', 'c', 'd'].indexOf('b') > -1; // true
['a', 'b', 'c', 'd'].includes('b'); // true
複製程式碼
includes()與indexOf對比:
includes
相比indexOf
更具語義化,includes
返回的是是否存在的具體結果,值為布林值,而indexOf
返回的是搜尋值的下標。includes
相比indexOf
更準確,includes
認為兩個NaN
相等,而indexOf
不會。
let a = [1, NaN, 3];
a.indexOf(NaN); // -1
a.includes(NaN); // true
複製程式碼
另外在判斷+0
與-0
時,includes
和indexOf
的返回相同。
[1, +0, 3, 4].includes(-0); // true
[1, +0, 3, 4].indexOf(-0); // 1
複製程式碼
參考資料
1.MDN 索引集合類
2.MDN 陣列物件
3.W3school JavaScript Array 物件
本部分內容到這結束
Author | 王平安 |
---|---|
pingan8787@qq.com | |
博 客 | www.pingan8787.com |
微 信 | pingan8787 |
每日文章推薦 | github.com/pingan8787/… |
JS小冊 | js.pingan8787.com |
歡迎關注我的微信公眾號【前端自習課】