【重溫基礎】10.數組

本文是 重溫基礎 系列文章的第十篇。
今日感覺:平安夜,多棒。前端

系列目錄:git

本章節複習的是JS中的數組,以索引進行排序。 github

前置知識:
數組是一個有序的數據集合,使用數組名稱和索引進行訪問。正則表達式

let arr = [1,2,3];
arr[0] = 1;

在JavaScript中數組沒有明確數據類型。segmentfault

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;

若傳入的數組長度不是整數,則報錯:app

let arr = new Array(3.5); 
let arr = Array(3.5); 
let arr = [];
arr.length = 3.5;
//Uncaught RangeError: Invalid array length

其中要注意這兩種建立方法是不一樣的:ide

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()

對數組的元素進行排序,改變原數組
可接受一個回調方法做爲比較函數,來決定排序方式。
比較函數應該具備兩個參數 ab,返回值以下:
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時,includesindexOf的返回相同。

[1, +0, 3, 4].includes(-0);   // true
[1, +0, 3, 4].indexOf(-0);    // 1

參考資料

1.MDN 索引集合類
2.MDN 數組對象
3.W3school JavaScript Array 對象


本部份內容到這結束

Author 王平安
E-mail pingan8787@qq.com
博 客 www.pingan8787.com
微 信 pingan8787
每日文章推薦 https://github.com/pingan8787...
JS小冊 js.pingan8787.com

歡迎關注微信公衆號【前端自習課】天天早晨,與您一塊兒學習一篇優秀的前端技術博文 .

相關文章
相關標籤/搜索