1. 程式人生 > >【重溫基礎】10.陣列

【重溫基礎】10.陣列

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

系列目錄:

本章節複習的是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()

對陣列的元素進行排序,改變原陣列
可接受一個回撥方法作為比較函式,來決定排序方式。
比較函式應該具有兩個引數 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