## 數組
> 數組是值的有序集合,每個值叫做一個元素,而每個元素在數組中有一個位置,以數字表示,稱為索引。
* JavaScript數組的索引是基于零的32位數值,第一個元素索引為0,數組最大能容納4294967295(即2^32-1)個元素。
* JavaScript數組是動態的,根據需要它們會增長或縮減,并且在創建數組時無需聲明一個固定的大小或者在數組大小變化時無需重新分配空間。
* JavaScript數組可能是稀疏的,數組元素的索引不一定要連續的,它們之間可以有空缺。
* 每個JavaScript數組都有一個length屬性,針對非稀疏數組,該屬性就是數組元素的個數。針對稀疏數組,length比所有元素的索引都要大。## 創建數組
## 創建數組
### 1、最簡單的方法是使用數組直接量(字面量)創建數組。
~~~
var empty = []; //沒有元素的數組
var arr = [1.4, true, "a",]; //3個不同類型的元素和結尾的逗號
~~~
數組直接量中的值也不一定必須是常量,它們可以是任意的表達式:
~~~
var number = 1;
var list = [number, number+1, number+2];
~~~

如果省略數組直接量中的某個值,省略的元素用empty表示(就是沒有這個元素),訪問的話會返回undefined。
~~~
var count = [1,,3]; // 數組打印出來是(3) [1, empty, 3], count[1] === undefined是true。
var undefs = [,,]; // 數組直接量語法允許有可選的結尾的逗號,顧[,,]只有兩個元素而非三個,undefs.length 是 2
~~~
### 2、構造函數Array()創建數組
調用時沒有參數,等同于[ ],創建一個沒有任何元素的空數組
~~~
var?arr =?new?Array();
~~~
調用時有一個數值參數,它指定長度
~~~
var?arr =?new?Array(10)?// (10) [empty × 10]
~~~
顯式指定兩個或者多個數組元素或者數組元素的一個非數值元素
~~~
var?arr =?new?Array(1,2,3,"one");
~~~
### 3、ES6的一些方法
(1)`Array.of()`返回由所有參數組成的數組,不考慮參數的數量或類型,如果沒有參數就返回一個空數組(ES6新增)
** 參數:**
elementN 任意個參數,將按順序成為返回數組中的元素。
**注意:**
of() 可以解決上述構造器因參數個數不同,導致的行為有差異的問題(參數只有一個數值時,構造函數會把它當成數組的長度)。
~~~
Array.of(1,2,3); // [1,2,3]
Array.of(1,{a:1},null,undefined) // [1, {a:1}, null, undefined]
// 只有一個數值參數時
let B = new Array(3); // (3) [empty × 3]
let C = Array.of(3); // [3]
~~~
返回值:新的 Array 實例。
(2)`Array.from()`從一個類數組或可迭代對象中創建一個新的數組**(ES6新增)**
**參數:**
* 第一個參數:想要轉換成數組的類數組或可迭代對象
* 第二個參數(可選):回調函數,類似數組的map方法,對每個元素進行處理,將處理后的值放入返回的數組。
* 第三個參數(可選):綁定回調函數的this對象
~~~
// 有length屬性的類數組
Array.from({length:5},(v,i) => i) //[0, 1, 2, 3, 4]
// 部署了Iterator接口的數據結構 比如:字符串、Set、NodeList對象
Array.from('hello') // ['h','e','l','l','o']
Array.from(new Set(['a','b'])) // ['a','b']
// 傳入一個數組生成的是一個新的數組,引用不同,修改新數組不會改變原數組
let arr1 = [1,2,3]
let arr2 = Array.from(arr);
arr2[1] = 4;
console.log(arr1,arr2)
//[1, 2, 3] [1, 4, 3]
~~~
返回值:**新的 Array 實例。**
**知識點**
~~~
//數組合并去重
function combine(){
let arr = [].concat.apply([], arguments); //沒有去重復的新數組,之后用Set數據結構的特性來去重
return Array.from(new Set(arr));
}
var m = [1, 2, 2], n = [2,3,3];
console.log(combine(m,n));
~~~
## 數組方法
### **1、會改變原數組的方法**
#### 1. push() 方法在數組的尾部添加一個或多個元素,并**返回數組的長度**
參數: item1, item2, ..., itemX ,要添加到數組末尾的元素
~~~
let arr = [1,2,3];
let length = arr.push('末尾1','末尾2'); // 返回數組長度
console.log(arr,length)
// [1, 2, 3, "末尾1", "末尾2"] 5
~~~
返回值:**數組的長度**
#### 2. pop() 方法刪除數組的最后一個元素,減小數組長度并**返回它刪除的值**。
參數:無
~~~
//組合使用push()和pop()能夠用JavaScript數組實現先進后出的棧
let stack = [];
stack.push(1,2) // 返回長度2,這時stack的值是[1,2]
stack.pop() // 返回刪除的值2,這時stack的值是[1]
~~~
返回值:**從數組中刪除的元素(當數組為空時返回undefined)。**
#### 3\. unshift() 方法在數組的頭部添加一個或多個元素,并將已存在的元素移動到更高索引的位置來獲得足夠的空間,最后**返回數組新的長度**。
參數: item1, item2, ..., itemX ,要添加到數組開頭的元素
~~~
let arr = [3,4,5];
let length = arr.unshift(1,2); // 返回長度是5
console.log(arr, length)
//[1, 2, 3, 4, 5] 5
~~~
**注意:**當調用unshift()添加多個參數時,參數時一次性插入的,而非一次一個地插入。就像是上例添加1和2,他們插入到數組中的順序跟參數列表中的順序一致,而不是\[2,1,3,4,5\]。
****返回值:**返回數組新的長度。**
#### 4\. shift() 方法刪除數組的第一個元素并將其返回,然后把所有隨后的元素下移一個位置來填補數組頭部的空缺,返回值是**刪除的元素**
參數: 無。
~~~
let arr = [1,2,3];
let item = arr.shift(); // 返回刪除的值1
console.log(arr, item)
// [2, 3] 1
~~~
****返回值:**從數組中刪除的元素; 如果數組為空則返回undefined 。**
#### 5\. splice() 方法是在數組中插入或刪除元素的通用方法
**語法**
`array.splice(start[, deleteCount[, item1[, item2[, ...]]]])`
**參數:**
`start`?
指定修改的開始位置(從0計數)。如果超出了數組的長度,則從數組末尾開始添加內容;如果是負值,則表示從數組末位開始的第幾位(從-1計數);若只使用start參數而不使用deleteCount、item,如:array.splice(start) ,表示刪除\[start,end\]的元素。
`deleteCount`(可選)
整數,表示要移除的數組元素的個數。如果 deleteCount 是 0,則不移除元素。這種情況下,至少應添加一個新元素。如果 deleteCount 大于start 之后的元素的總數,則從 start 后面的元素都將被刪除(含第 start 位)。
如果deleteCount被省略,則其相當于(arr.length - start)。
`item1, item2, ...`(可選)
要添加進數組的元素,從start 位置開始。如果不指定,則 splice() 將只刪除數組元素。
****返回值:**由被刪除的元素組成的一個數組。如果只刪除了一個元素,則返回只包含一個元素的數組。如果沒有刪除元素,則返回空數組。**
~~~
// start不超過數組長度(以下操作是連續的)
let arr = [1,2,3,4,5];
arr.splice(2) // arr是[1,2],返回值是[3,4,5]
arr.splice(1,1) // arr是[1],返回值是[2]
arr.splice(0,3) // arr是[],返回值是[1],因為此時數組從第0位開始不夠3位,所以是刪除從0開始到最后的所有元素。
// start大于數組長度(以下操作是連續的)
let arr = [1,2,3,4,5];
arr.splice(5) // arr是[1,2,3,4,5],返回值是[]
arr.splice(5,3,6) // arr是[1,2,3,4,5,6],返回值是[]
arr.splice(5,3,7) // arr是[1,2,3,4,5,7] 返回值是[6]
// start是負數(以下操作是連續的)
let arr = [1,2,3,4,5];
arr.splice(-3,2); // arr是[1,2,5], 返回值是[3,4]
arr.splice(-4); // arr是[],返回值是[1,2,5]
// 插入數組時,是插入數組本身,而不是數組元素
let arr = [1,4,5];
arr.splice(1,0,[2,3]) // arr是[1,[2,3],4,5],返回值是[]
~~~
#### 6\. sort() 方法將數組中的元素排序并**返回排序后的數組**
參數:
`compareFunction`(可選) 用來指定按某種順序進行排列的函數。如果省略,元素按照轉換為的字符串的各個字符的Unicode位點進行排序。
如果指明了 compareFunction ,那么數組會按照調用該函數的返回值排序。即 a 和 b 是兩個將要被比較的元素:
* 如果 compareFunction(a, b) 小于 0 ,那么 a 會被排列到 b 之前;
* 如果 compareFunction(a, b) 等于 0 , a 和 b 的相對位置不變。備注: ECMAScript 標準并不保證這一行為,而且也不是所有瀏覽器都會遵守(例如 Mozilla 在 2003 年之前的版本);
* 如果 compareFunction(a, b) 大于 0 , b 會被排列到 a 之前。
* compareFunction(a, b) 必須總是對相同的輸入返回相同的比較結果,否則排序的結果將是不確定的。
~~~
var stringArray = ["Blue", "Humpback", "Beluga"];
var numberArray = [40, 1, 5, 200];
function compareNumbers(a, b){
return a - b;
}
console.log('stringArray:' + stringArray.join());
console.log('Sorted:' + stringArray.sort());
console.log('numberArray:' + numberArray.join());
// 沒有使用比較函數時,數字并不會按照我們設想的那樣排序
console.log('Sorted without a compare function:'+ numberArray.sort());
console.log('Sorted with compareNumbers:'+ numberArray.sort(compareNumbers));
//打印如下
// stringArray: Blue,Humpback,Beluga
// Sorted: Beluga,Blue,Humpback
// numberArray: 40,1,5,200
// Sorted without a compare function: 1,200,40,5
// Sorted with compareNumbers: 1,5,40,200
~~~
****返回值:**返回排序后的數組。原數組已經被排序后的數組代替。**
#### 7\. reverse() 方法將數組中的元素顛倒順序,返回逆序的數組。
參數: 無
~~~
let arr = [1,2,3];
arr.reverse() // arr是[3,2,1],返回值是[3,2,1]
~~~
****返回值:**返回順序顛倒后的數組。原數組已經被排序后的數組代替。**
#### 8\. copyWithin() 方法淺復制數組的一部分到同一數組中的另一個位置,并返回它,而不修改其大小。**(ES6新增)**
**語法:**
`arr.copyWithin(target[, start[, end]])`
**參數:**
`target`
0 為基底的索引,復制序列到該位置。如果是負數,target 將從末尾開始計算。
如果 target 大于等于 arr.length,將會不發生拷貝。如果 target 在 start 之后,復制的序列將被修改以符合 arr.length。
`start`
0 為基底的索引,開始復制元素的起始位置。如果是負數,start 將從末尾開始計算。
如果 start 被忽略,copyWithin 將會從0開始復制。
`end`
0 為基底的索引,開始復制元素的結束位置。copyWithin 將會拷貝到該位置,**但不包括 end 這個位置的元素**。如果是負數, end 將從末尾開始計算。
如果 end 被忽略,copyWithin 將會復制到 arr.length。
****返回值:**改變了的數組。**
~~~
[1, 2, 3, 4, 5].copyWithin(-2);
// [1, 2, 3, 1, 2]
[1, 2, 3, 4, 5].copyWithin(0, 3);
// [4, 5, 3, 4, 5]
[1, 2, 3, 4, 5].copyWithin(0, 3, 4);
// [4, 2, 3, 4, 5]
[1, 2, 3, 4, 5].copyWithin(-2, -3, -1);
// [1, 2, 3, 3, 4]
// copyWithin 函數是設計為通用的,其不要求其 this 值必須是一個數組對象。
[].copyWithin.call({length: 5, 3: 1}, 0, 3);
// {0: 1, 3: 1, length: 5}
~~~
#### 9\. fill() 方法用一個固定值填充一個數組中從起始索引到終止索引內的全部元素。**(ES6新增)**
**語法:**
`arr.fill(value[, start[, end]])`
**參數:**
`value`用來填充數組元素的值。
`start`(可選) 起始索引,默認值為0。
`end`(可選) 終止索引,默認值為 this.length。
如果 start 是個負數, 則開始索引會被自動計算成為 length+start, 其中 length 是 this 對象的 length 屬性值. 如果 end 是個負數, 則結束索引會被自動計算成為 length+end。
****返回值:**修改后的數組**
~~~
[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 方法故意被設計成通用方法, 該方法不要求 this 是數組對象。
[].fill.call({ length: 3 }, 4); // {0: 4, 1: 4, 2: 4, length: 3}
~~~
### **2、不改變原數組的方法**
#### 1\. slice() 方法返回一個從開始到結束(不包括結束)選擇的數組的一部分**淺拷貝**到一個新數組對象。且原始數組不會被修改。
**參數:**
`begin`(可選)
從該索引處開始提取原數組中的元素(從0開始)。
**如果該參數為負數,則表示從原數組中的倒數第幾個元素開始提取**,slice(-2)表示提取原數組中的倒數第二個元素到最后一個元素(包含最后一個元素)。
如果省略 begin,則 slice 從索引 0 開始。
`end`(可選)
在該索引處結束提取原數組元素(從0開始)。
slice會提取原數組中索引從 begin 到 end 的所有元素(**包含begin,但不包含end**)。
slice(1,4) 提取原數組中的第二個元素開始直到第四個元素的所有元素 (索引為 1, 2, 3的元素)。
**如果該參數為負數, 則它表示在原數組中的倒數第幾個元素結束抽取**。 slice(-2,-1)表示抽取了原數組中的倒數第二個元素到最后一個元素(不包含最后一個元素,也就是只有倒數第二個元素)。
如果 end 被省略,則slice 會一直提取到原數組末尾。
**如果 end 大于數組長度,slice 也會一直提取到原數組末尾**。
****返回值:**一個含有提取元素的新數組**
~~~
let arr = [1,2,3,4,5];
let arr1 = arr.slice(1,3); // arr是[1,2,3,4,5], arr1是[2,3]
let arr2 = arr.slice(-2,-1); // arr是[1,2,3,4,5], arr2是[4]
// 開始位置在結束位置后面,得到的數組是空
let arr3 = arr.slice(-2, -3); // arr是[1,2,3,4,5], arr3是[]
let arr4 = arr.slice(2, 1); // arr是[1,2,3,4,5], arr4是[]
//如果元素是個對象引用 (不是實際的對象),slice 會拷貝這個對象引用到新的數組里。兩個對象引用都引用了同一個對象。如果被引用的對象發生改變,則新的和原來的數組中的這個元素也會發生改變。
let arr = [{name: 'xiaoming'}];
let arr1 = arr.slice(); // arr是[{name: xiaoming}],arr1是[{name: 'xiaoming'}]
arr1[0].name = 'xiaogang'; // arr是[{name: 'xiaogang'}],arr1是[{name: 'xiaogang'}]
// 對于字符串、數字及布爾值來說(不是 String、Number 或者 Boolean 對象),slice 會拷貝這些值到新的數組里。在別的數組里修改這些字符串或數字或是布爾值,將不會影響另一個數組。
let arr = [1,2,3];
let arr1 = arr.slice(); // arr是[1,2,3],arr1是[1,2,3]
arr1[1] = "two"; // arr是[1,2,3],arr1是[1,"two",3]
// 當然,如果向兩個數組任一中添加了新元素(簡單或者引用類型),則另一個不會受到影響。
~~~
#### 2\. join() 方法將數組(或一個類數組對象)中所有元素都轉化為字符串并連接在一起,返回最后生成的字符串。
**參數:**
`separator`(可選)
指定一個字符串來分隔數組的每個元素。
如果有(separator),將分隔符轉換為字符串。
如果省略(),數組元素用逗號分隔。默認為 ","。
如果separator是空字符串(""),則所有元素之間都沒有任何字符。
~~~
let num = [1,2,3];
let str1 = num.join(); // 1,2,3
let str2 = num.join(', ') // 1, 2, 3
let str3 = num.join('') // 123
//所有的數組元素被轉換成字符串,再用一個分隔符將這些字符串連接起來。如果元素是undefined 或者null, 則會轉化成空字符串。
let num = [1,null,3];
let str1 = num.join(); // 1,,3
//如果數組中的元素是數組,會將里面的數組也調用join()
let num = [[1,2],3];
let str1 = num.join('-'); // 1,2-3
// 如果數組中的元素是對象,對象會被轉為[object Object]字符串
let num = [{num: 1},2,3];
let str1 = num.join('-'); // [object Object]-2-3
~~~
****返回值:**一個所有數組元素連接的字符串。如果 arr.length 為0,則返回空字符串**
**知識點**
~~~
// 扁平化簡單的二維數組
const arr = [11, [22, 33], [44, 55], 66];
const flatArr = arr.join().split(','); // ["11", "22", "33", "44", "55", "66"]
~~~
#### 3\. toString() 方法將數組的每個元素轉化為字符串(如有必要將調用元素的toString()方法)并且輸出用逗號分割的字符串列表。返回一個字符串表示數組中的元素
**參數:**無
~~~
[1,2,3].toString(); // 1,2,3
[1,[2,'c']].toString(); //1,2,c
// 以上與不使用任何參數調用join()方法返回的字符串是一樣的。
// 以下的這個例子要跟下面的toLocaleString對照看
[{a:1},1,new Date()].toString() //"[object Object],1,Sat Jul 07 2018 18:43:45 GMT+0800 (中國標準時間)"
~~~
**注意:**當數組和字符串操作的時候,js 會調用這個方法將數組自動轉換成字符串
~~~
[1,2,3]+'abc'?//1,2,3abc
~~~
****返回值:**返回一個字符串表示數組中的元素**
**知識點**
~~~
// 扁平化簡單的二維數組
const arr = [11, [22, 33], [44, 55], 66];
const flatArr = arr.toString().split(','); // ["11", "22", "33", "44", "55", "66"]
~~~
#### 4\. toLocaleString() 數組中的元素將使用各自的 toLocaleString 方法轉成字符串,這些字符串將使用一個特定語言環境的字符串(例如一個逗號 ",")隔開。
**參數:(還有待考證,我試了一下沒用,看了一下ECMA的官網,確實是標注有兩個可選參數的)**
`locales`(可選) 帶有BCP 47語言標記的字符串或字符串數組
`options`(可選) 一個可配置屬性的對象
~~~
//數組中的元素將會使用各自的 toLocaleString 方法:
// Object: Object.prototype.toLocaleString()
// Number: Number.prototype.toLocaleString()
// Date: Date.prototype.toLocaleString()
let prices = ['¥7', 500, 8123, 12];
// 不帶參數
prices.toLocaleString(); // "¥7,500,8,123,12"
//帶參數
prices.toLocaleString('ja-JP', { style: 'currency', currency: 'JPY' }); // "¥7,500,8,123,12"
//MDN上的舉例中說是 "¥7,¥500,¥8,123,¥12",在瀏覽器和Node中驗證了返回的都是 "¥7,500,8,123,12" 啊!
// 以下的這個例子要跟上面的toString對照看
[{a:1},1,new Date()].toLocaleString() //"[object Object],1,2018/7/7 下午6:45:00"
~~~
****返回值:**表示數組元素的字符串。**
#### 5\. concat() 方法用于合并兩個或多個數組。此方法不會更改現有數組,而是返回一個新數組。
它的元素包括調用concat()的原始數組的元素和concat()的每個參數,但是要注意,concat()不會遞歸扁平化數組的數組,concat()也不會修改調用的數組。
**參數:**
`valueN`(可選) 將(多個)數組和/或值連接成新數組。
~~~
[1,2,3].concat([4,5,6],[7,8,9]) // [1, 2, 3, 4, 5, 6, 7, 8, 9]
['a','b','c'].concat(1,[2,3],[[4,5]]) // ["a", "b", "c", 1, 2, 3, [4,5]]
// concat方法不會改變this或任何作為參數提供的數組,而是返回一個淺拷貝,所以原始數組和新數組都引用相同的對象。 如果引用的對象被修改,新數組和原始數組都會變。
let obj = {a: 1};
let arr1 = [2,obj];
let arr2 = [1].concat(arr1);
console.log(arr1,arr2) //[2,{a:1}],[1,2,{a:1}]
//記錄下上面的打印結果之后修改obj
obj.a = 2;
console.log(arr1,arr2) ////[2,{a:2}],[1,2,{a:2}]
// 說了是淺拷貝,而且原數組也不改變,那我們就可以用它來實現數組的淺拷貝功能
let num1 = [1,2,3];
//第一種
let num2 = num1.concat();
//第二種
let num2 = [].concat(num1);
num2[0] = 'a';
console.log(num1,num2); // [1, 2, 3] ["a", 2, 3]
~~~
****返回值:**新的 Array 實例**
**知識點**
~~~
// concat 和擴展運算符可以快速扁平化數組
const arr = [11, [22, 33], [44, 55], 66];
const flatArr = [].concat(...arr); // [11, 22, 33, 44, 55, 66]
~~~
#### 6\. isArray() 用于確定傳遞的值是否是一個 Array。
**參數:**
`obj`需要檢測的值。
~~~
// 下面的函數調用都返回 true
Array.isArray([]);
Array.isArray([1]);
Array.isArray(new Array());
// 這里注意:Array.prototype 也是一個數組,一個屬性值不是索引的數組。[constructor: ?, concat: ?, find: ?, findIndex: ?, pop: ?, …]
Array.isArray(Array.prototype);
// 下面的函數調用都返回 false
Array.isArray();
Array.isArray({});
Array.isArray(null);
Array.isArray(undefined);
Array.isArray(17);
Array.isArray('Array');
Array.isArray(true);
Array.isArray(false);
Array.isArray({ __proto__: Array.prototype });
~~~
****返回值:**如果對象是 Array,則為true; 否則為false。**
**知識點**
~~~
//判斷數組的歷程
// step one: 使用constructor
var a = [1];
console.log(a.constructor === Array) // true
// 但是原型的contructor屬性是可以被改寫的,例如在原型繼承的時候,我們都是要把繼承過來的prototype的constructor改寫成我們當前的
var a = [1];
a.__proto__.constructor = '1';
console.log(a.constructor === Array) // false
// step two : 使用instanceof
var a = [1];
console.log(a instanceof Array) // true
//但是instanceof不能檢測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]
arr instanceof Array; // false
// step three :萬無一失的Object.prototype.toString.call
Array.isArray = function(arg) {
return Object.prototype.toString.call(arg) === '[object Array]';
};
// step four : Array.isArray()
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]
Array.isArray(arr); // true,也可以檢測iframes的數組
~~~
### **3、數組遍歷、映射、過濾、檢測、簡化等方法**
介紹方法之前,先對這些數組方法做一個概述:
* 首先,大多數方法的第一個參數接收一個函數,并且對數組的每個元素(或一些元素)調用一次該函數。如果是稀疏數組,對不存在的元素不調用該函數。大多數情況下,調用提供的函數使用三個參數:數組元素、元素的索引和數組本身。通常,只需要第一個參數值,可以忽略后兩個參數。
* 大多數方法,第二個參數是可選的。如果有第二個參數,則調用的第一個函數參數被看做是第二個參數的方法,即當執行第一個函數參數時用作this的值(參考對象)。
* 方法的返回值很重要,不同的方法處理返回值的方式也不一樣。
**下面這些方法運行時的規則:**
1. 對于空數組是不會執行回調函數的
2. 對于已在迭代過程中刪除的元素,或者空元素會跳過回調函數
3. 遍歷次數在第一次循環前就會確定,再添加到數組中的元素不會被遍歷。
4. 如果已經存在的值被改變,則傳遞給 callback 的值是遍歷到他們那一刻的值。
5. 已刪除的項不會被遍歷到。如果已訪問的元素在迭代時被刪除了(例如使用 shift()) ,之后的元素將被跳過
#### 1\. forEach() 方法從頭到尾遍歷數組,為每個元素調用指定的函數。
**參數:**
`callback`為數組中每個元素執行的函數,該函數接收三個參數:
1. `currentValue(當前值)`數組中正在處理的當前元素。
2. `index(索引)`數組中正在處理的當前元素的索引。
3. `array`forEach()方法正在操作的數組。
`thisArg`(可選) 當執行回調函數時用作this的值(參考對象)。默認值為undefined
**注意:**
1. forEach無法中途退出循環,只能用return退出本次回調,進行下一次回調,如果要提前終止,可以把forEach方法放在try塊中,并能拋出一個異常,但這種方法是不推薦的。
2. 它與之后會說到的幾個方法不同,總是返回 undefined值,即使你return了一個值。
~~~
// 1、 空元素不遍歷,undefined和null是會遍歷的。
let numberArr = [1,2,,3];
numberArr.forEach(function (value,index,array) {
console.log(value,index,array)
})
//打印信息如下,可見空元素是不會遍歷的
//1 0 [1, 2, empty, 3]
//2 1 [1, 2, empty, 3]
//3 3 [1, 2, empty, 3]
let nullArr = [1,2,null,3];
nullArr.forEach(function (value,index,array) {
console.log(value,index,array)
})
//打印信息如下,null是會遍歷的
//1 0 (4) [1, 2, null, 3]
//2 1 (4) [1, 2, null, 3]
//null 2 (4) [1, 2, null, 3]
//3 3 (4) [1, 2, null, 3]
//2、已刪除的項不會被遍歷到。如果已訪問的元素在迭代時被刪除了,之后的元素將被跳過
let numberArr = [1,2,3];
numberArr.forEach(function (value,index,array) {
if(index === 0) {
delete numberArr[2]; //刪除第三項
//或者numberArr.pop()
}
console.log(value,index,array)
})
//打印信息如下:
// 1 0 (3) [1, 2, empty]
// 2 1 (3) [1, 2, empty]
let numberArr1 = [1,2,3,4];
numberArr1.forEach(function (value,index,array) {
if(index === 1) {
numberArr1.shift() //遍歷到第二項的時候,刪除第一項
}
console.log(value,index,array)
})
// 打印信息如下,遍歷到第二項的時候,刪除第一項,會跳過第三項
// 1 0 (4) [1, 2, 3, 4]
// 2 1 (3) [2, 3, 4]
// 4 2 (3) [2, 3, 4]
// 3、forEach 遍歷的范圍在第一次調用 callback 前就會確定。調用forEach 后添加到數組中的項不會被 callback 訪問到。如果已經存在的值被改變,則傳遞給 callback 的值是 forEach 遍歷到他們那一刻的值。
let arr = [1,2,3];
arr.forEach(function (value,index,array) {
if(index === 0) {
arr.push('新增的不會被遍歷到')
arr[2] = 4;
}
console.log(value,index,array)
})
// 1 0 (4) [1, 2, 4, "新增的不會被遍歷到"]
// 2 1 (4) [1, 2, 4, "新增的不會被遍歷到"]
// 4 2 (4) [1, 2, 4, "新增的不會被遍歷到"]
// 4、使用thisArg參數 和 箭頭函數使用thisArg
let arr = [1,2,3];
let obj = {arr: 'thisArg'}
arr.forEach(function () {
console.log(this.arr)
},obj)
// 打印三次 'thisArg'
let arr = [1,2,3];
let obj = {arr: 'thisArg'}
arr.forEach(() => {
console.log(this.arr)
},obj)
// 打印三次 undefined
// 5、forEach無法中途退出循環,只能用return退出本次回調,進行下一次回調
let arr = [1,2,3];
let result = arr.forEach((value) => {
if(value == 2) {
return value;
}
console.log(value)
})
console.log(result) // undefined ,即使中間return vlaue,也還是undefined
//打印value的值如下,說明return 并不能終止循環
// 1
// 3
~~~
****返回值:**undefined**
#### 2\. map() 方法創建一個新數組,其結果是該數組中的每個元素都調用一個callback函數后返回的結果。
**參數:**(之前說過,大多說方法都會是這樣一些參數)
`callback`生成新數組元素的函數,使用三個參 這個函數跟forEach()的函數不同的是,傳遞給map()的函數應該有返回值。
1. `currentValue`callback 的第一個參數,數組中正在處理的當前元素。
2. `index`callback 的第二個參數,數組中正在處理的當前元素的索引。
3. `array`callback 的第三個參數,map 方法被調用的數組。
`thisArg`(可選) 執行 callback 函數時 使用的this 值。
**注意:**map() 返回的是新數組,它不修改調用的數組。如果是稀疏數組,返回的也是相同方式的稀疏數組:它具有相同的長度,相同索引的缺失元素(因為空值不會調用函數)
~~~
let number = [1,2,3];
let doubles = number.map(function (value) {
return value * 2;
})
console.log(number, doubles)
// [1,2,3] [2,4,6]
~~~
****返回值:**一個新數組,每個元素都是回調函數的結果**
**知識點**
不要用 map 代替 forEach,map 會創建一個新的數組,占用內存。如果你不用 map 的返回值,那你就應當使用 forEach
#### 3\. filter() 方法返回的數組元素是調用的數組的一個子集。傳入的函數時用來邏輯判定的,該函數返回 true 或 false,如果返回值為true或能轉化為true的值,那么傳遞給判斷函數的元素就是這個子集的成員,它將被添加倒一個作為返回值的數組中。
**參數:**
`callback`用來測試數組的每個元素的函數。調用時使用參數 (element, index, array)。返回true表示保留該元素(通過測試),false則不保留。它接受三個參數:
1. `element`當前在數組中處理的元素
2. `index`(可選) 正在處理元素在數組中的索引
3. `array`(可選)調用了filter篩選器的數組
`thisArg`(可選)可選。執行 callback 時的用于 this 的值。
**注意:**
1. callback 只會在已經賦值的索引上被調用,對于那些已經被刪除或者從未被賦值的索引不會被調用。也就是說filter()會跳過稀疏數組中缺少的元素,它的返回數組總是稠密的,可以用這個方法壓縮稀疏數組的空缺。
2. filter 不會改變原數組,它返回過濾后的新數組。
~~~
let number = [1,2,3,4,5,6];
let small = number.filter((value) => {
return value < 4;
})
console.log(number,small)
// 打印 [1, 2, 3, 4, 5, 6] [1, 2, 3]
//壓縮稀疏數組的空缺
let arr = [1,2,3,,5];
let arr1 = arr.filter(() => true);
console.log(arr,arr1)
// 打印 [1, 2, 3, empty, 5] [1, 2, 3, 5]
~~~
****返回值:**一個新的通過測試的元素的集合的數組,如果沒有通過測試則返回空數組。**
#### 4\. every() 方法測試數組的所有元素是否都通過了指定函數的測試。當且僅當針對數組中的所有元素調用判定函數都返回true,它才返回true。
**參數:**
`callback`用來測試每個元素的函數。
`thisArg`執行 callback 時使用的 this 值。
**注意:**
1. every 方法為數組中的每個元素執行一次 callback 函數,callback 只會為那些已經被賦值的索引調用。不會為那些被刪除或從來沒被賦值的索引調用。every 方法在callback第一次返回false后就返回false,然后終止遍歷。但如果callback一直返回true,它將會遍歷整個數組,最終返回true。
2. 空數組上調用every方法,返回 true,因為空數組沒有元素,所以空數組中所有元素都符合給定的條件
3. every 不會改變原數組
~~~
let arr = [12,34,5,23,44];
let num = 0;
let result = arr.every(function (element, index, array) {
num++;
return element > 10;
})
console.log(result,num) // 打印 false 3
// 可見發現5這個小于10的元素后,遍歷立即終止,num為3
let arr = [12,34,,23,44];
let num = 0;
let result = arr.every(function (element, index, array) {
num++;
return element > 10;
})
console.log(result,num) // 打印 true 4
// 不會遍歷沒有賦值的索引位置,所以num為4
let result = [].every(function (element, index, array) {
return element > 10;
})
console.log(result) // 打印 true
~~~
****返回值:**一個布爾值,當所有的元素都符合條件才返回true,否則返回false**
#### 5\. some() 方法測試數組中的某些元素是否通過由提供的函數實現的測試。當數組中至少有一個元素調用判定函數返回true,它就返回true,當且僅當數組中的所有元素調用判定函數都返回false,它才返回false。
**參數:**
`callback`用來測試每個元素的函數
`thisArg`可選 執行 callback 時使用的 this 值。
**注意:**
1. some 為數組中的每一個元素執行一次 callback 函數,直到找到一個使得 callback 返回一個“真值”,這時,some 將會立即返回 true。否則,some 返回 false。callback 只會在那些”有值“的索引上被調用,不會在那些被刪除或從來未被賦值的索引上調用。
2. some 被調用時不會改變數組。
3. 空數組調用some,返回false
~~~
// 一個簡單的例子說明
function isBiggerThan10(element, index, array) {
return element > 10;
}
[2, 5, 8, 1, 4].some(isBiggerThan10); // false
[12, 5, 8, 1, 4].some(isBiggerThan10); // true
// 實現一個跟includes方法類似的功能
let arr = [1,2,3];
function include(value) {
return arr.some((element) => {
return element === value;
})
}
include(2) // true
include(4) // false
let result = [].some(function (element, index, array) {
return element > 10;
})
console.log(result) // 打印 false
~~~
****返回值:**只要數組中的任意一個元素在回調函數中返回的是真值,就返回true,否則為false**
#### 6\. reduce() 和 reduceRight() 這兩個方法使用指定的函數將數組元素進行組合,生成單個值。這在函數式編程中是常見的操作,也可以稱為“注入”和“折疊”。reduceRight() 和 reduce() 工作原理是一樣的,不同的是reduceRight() 按照數組索引從高到低(從右到左)處理數組,而不是從低到高。
**參數:**
`callback`執行數組中每個值的函數,包含四個參數:
1. `accumulator`累加器累加回調的返回值; 它是上一次調用回調時返回的累積值,或initialValue(如下所示)。
2. `currentValue`數組中正在處理的元素。
3. `currentIndex`(可選) 數組中正在處理的當前元素的索引。 如果提供了initialValue,則索引號為0,否則為索引為1。
4. `array`(可選) 調用reduce的數組
`initialValue`(可選) 用作第一個調用 callback的第一個參數的值。 如果沒有提供初始值,則將使用數組中的第一個元素。 在沒有初始值的空數組上調用 reduce 將報錯。
**注意:**
1. reduce為數組中的每一個元素依次執行callback函數,不包括數組中被刪除或從未被賦值的元素,回調函數第一次執行時,accumulator 和currentValue的取值有兩種情況:調用reduce時提供initialValue,accumulator取值為initialValue,currentValue取數組中的第一個值;沒有提供 initialValue,accumulator取數組中的第一個值,currentValue取數組中的第二個值。即:如果沒有提供initialValue,reduce 會從索引1的地方開始執行 callback 方法,跳過第一個索引。如果提供initialValue,從索引0開始。
2. 如果數組為空且沒有提供initialValue,會拋出TypeError 。如果數組僅有一個元素(無論位置如何)并且沒有提供initialValue, 或者有提供initialValue但是數組為空,那么此唯一值將被返回**并且callback不會被執行**。
~~~
let arr = [1,2,3,4,5];
let sum = arr.reduce((x,y) => x + y,0);
console.log(sum) // 15
// 看一下initialValue傳和不傳的區別
let arr = [1,2,3,4,5];
arr.reduce(function (accumulator,currentValue,currentIndex,arr) {
console.log(currentIndex)
return accumulator + currentValue;
})
// 1,2,3,4,5 沒傳入initialValue,索引是從1開始
arr.reduce(function (accumulator,currentValue,currentIndex,arr) {
console.log(currentIndex)
return accumulator + currentValue;
},10)
// 0,1,2,3,4,5 傳入initialValue,索引從0開始
// 應用到二維數組展開
let arr = [[0, 1], [2, 3], [4, 5]].reduce(
(a, b) => a.concat(b)
);
console.log(arr)
// [0, 1, 2, 3, 4, 5]
~~~
****返回值:**函數累計處理的結果**
#### 7\. indexof() 方法返回在數組中可以找到一個給定元素的第一個索引,如果不存在,則返回-1。
**參數:**
`searchElement`要查找的元素
`fromIndex`(可選)開始查找的位置。
如果該索引值大于或等于數組長度,意味著不會在數組里查找,返回-1。
如果該索引值是負值,代表相對數組末尾的偏移量,即-1表示從最后一個元素開始查找,-2表示從倒數第二個元素開始查找,**注意的是,這并不改變其查找順序,查找順序仍然是從前向后查詢數組。**
如果該索引值是負值,其絕對值大于數組長度,則整個數組都將會被查詢。其默認值為0。
**注意:**indexOf 使用嚴格相等(即 ===)比較 searchElement 和數組中的元素。而且indexOf()不能識別`NaN`
~~~
let array = [2, 5, 9];
array.indexOf(2) // 0
array.indexOf(7) // -1
array.indexOf(9, 2) // 2
array.indexOf(9, 3) // -1
array.indexOf(2, -1) // -1
array.indexOf(2, -3) // 0
array.indexOf(2, -4) // 0
let array1 = [1,2,NaN];
array1.indexOf(NaN) // -1
~~~
****返回值:**首個被找到的元素在數組中的索引位置; 若沒有找到則返回 -1**
#### 8\. lastIndexOf() 跟indexOf()查找方向相反,方法返回指定元素在數組中的最后一個的索引,如果不存在則返回 -1。從數組的后面向前查找,從 fromIndex 處開始
**參數:**
searchElement 要查找的元素
fromIndex (可選)開始查找的位置。默認為數組的長度減 1,即整個數組都被查找。
如果該值大于或等于數組的長度,則整個數組會被查找。
如果為負值,將其視為從數組末尾向前的偏移。即使該值為負,數組仍然會被從后向前查找。
如果該值為負時,其絕對值大于數組長度,則方法返回 -1,即數組不會被查找。
**注意:**lastIndexOf 使用嚴格相等(即 ===)比較 searchElement 和數組中的元素。而且lastIndexOf()不能識別`NaN`
~~~
let array = [2,5,9,2];
array.lastIndexOf(9) // 2
array.lastIndexOf('9') // -1 嚴格相等
array.lastIndexOf(7) // -1
array.lastIndexOf(2,4) // 3
array.lastIndexOf(2,3) // 3
array.lastIndexOf(2,2) // 0
array.lastIndexOf(2,-1) // 3
array.lastIndexOf(2,-2) // 0
array.lastIndexOf(2,-4) // 0
array.lastIndexOf(2,-5) // -1
~~~
****返回值:**數組中最后一個符合元素的索引,如未找到返回-1**
#### 9\. includes() 方法用來判斷一個數組是否包含一個指定的值,根據情況,如果包含則返回 true,否則返回false。**ES7新增**
**參數:**
`searchElement`需要查找的元素值。
`fromIndex`(可選) 從該索引處開始查找 searchElement。默認為 0。如果為負值,則按升序從 array.length + fromIndex 的索引開始搜索。負值絕對值超過長數組度,從0開始搜索。
如果fromIndex 大于等于數組長度 ,則返回 false 。該數組不會被搜索。
**注意:**
includes解決了兩個indexOf的問題:
1. indexOf方法不能識別NaN
2. indexOf方法檢查是否包含某個值不夠語義化,需要判斷是否不等于-1,表達不夠直觀
~~~
[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, 3].includes(3, -4); // true
[1, 2, NaN].includes(NaN); // true
~~~
****返回值:**一個布爾值,根據情況,如果包含則返回 true,否則返回false。**
#### 10\. find() 和 findIndex() find 方法返回數組中滿足提供的測試函數的第一個元素的值。否則返回 undefined。findIndex 方法返回數組中滿足提供的測試函數的第一個元素的索引。否則返回-1。**(ES6新增)**
**參數:**這兩個方法跟其他的方法類似
`callback`在數組每一項上執行的函數,接收 3 個參數:
1. `element`當前遍歷到的元素。
2. `index`當前遍歷到的索引。
3. `array`數組本身。
`thisArg`可選,指定 callback 的 this 參數。
**注意:**
1. 這兩個方法對數組中的每一項元素執行一次 callback 函數,直至有一個 callback 返回 true。**在稀疏數組中,即使對于數組中不存在的條目的索引也會調用回調函數。**這意味著對于稀疏數組來說,該方法的效率要低于那些只遍歷有值的索引的方法。
2. 當找到一個callback判斷為true的元素,find方法會立即返回這個元素的值,否則返回 undefined。findIndex會立即返回該元素的索引。如果回調從不返回真值,或者數組的length為0,則findIndex返回-1。
3. 這兩個方法都不會修改所調用的數組
~~~
// 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) => isNaN(n)); // 返回索引4
// 稀疏數組
let a =[1,,3,4];
let index = 0;
a.find((n) => {
console.log(index++) //0,1,2 第二次是empty也會調用一次,而且返回為true,立即退出
return n === 3;
})
~~~
**
**返回值:****
1. find 方法,當某個元素通過 callback 的測試時,返回數組中的一個值,否則返回 undefined。
2. findIndex方法,返回數組中滿足提供的測試函數的第一個元素的索引。否則返回-1。
**知識點**
不要用 find() 代替 some(),通常混用是這種場景,find 返回第一個符合條件的值,直接拿這個值做 if 判斷是否存在,但是這個符合條件的值也有可能恰好為 0。
find 是找到數組中的值后對其進一步處理,一般用于對象數組的情況;some 才是檢查存在性;兩者不可混用。
#### 11\. keys() 方法返回一個新的Array迭代器,它包含數組中每個索引的鍵。**(ES6新增)**
#### 12\. values() 方法返回一個新的Array迭代器,它包含數組中每個索引的值。**(ES6新增)**
#### 13\. @@iterator 屬性和 values() 屬性的初始值均為同一個函數對象。數組的 iterator 方法,默認情況下與 values() 返回值相同,調用語法是`arr[Symbol.iterator]()`**(ES6新增)**
#### 14\. entries() 方法返回一個新的Array迭代器,該對象包含數組中每個索引的鍵/值對。**(ES6新增)**
**參數:**都是無。
**都是一個新的 Array 迭代器對象。**
~~~
for (let key of ['a', 'b'].keys()) {
console.log(key);
}
// 0
// 1
for (let value of ['a', 'b'].values()) {
console.log(value);
}
// 'a'
// 'b'
for (let value of ['a', 'b'][Symbol.iterator]()) {
console.log(value);
}
// 'a'
// 'b'
for (let [key, value] of ['a', 'b'].entries()) {
console.log(key, value);
}
// 0 "a"
// 1 "b"
~~~
## 擴展幾個概念
#### 1、數組的索引和對象key有什么關系?
數組是對象的特殊形式,使用方括號訪問數組元素和使用方括號訪問對象屬性一樣。JavaScript將指定的數字索引值轉換成字符串——索引1變成"1"——然后將其作為屬性名來使用。數組的特別之處在于,當使用小于2^32的非負整數作為屬性名時數組會自動維護其length屬性。
~~~
// 索引到屬性名的轉化
let arr = [1,2,3];
console.log(arr[1]) // 2
console.log(arr["1"]) // 2
~~~
所有的數組都是對象,可以為其創建任意名字的屬性,不過,只有在小于2^32的非負整數才是索引,數組才會根據需要更新length。事實上數組的索引僅僅是對象屬性名的一種特殊類型,這意味著JavaScript數組沒有“越界”錯誤的概念。當查詢任何對象中不存在的屬性時,不會報錯,只會得到undefined
~~~
let arr = [];
arr["a"] = 1;
console.log(arr,arr.length) // arr是[a:1] length是0
~~~
對于使用負數或非整數的情況,數值會轉換為字符串,字符串作為屬性名來用,當時只能當做常規的對象屬性,而非數組的索引。
~~~
let arr = [];
arr[-1.23] = 0;
console.log(arr,arr.length) // arr是[-1.23: 0] length是0
~~~
使用非負整數的字符串或者一個跟整數相等的浮點數時,它就當做數組的索引而非對象屬性。
~~~
let arr = [];
arr["100"] = 'a';
console.log(arr,arr.length) // arr 是[empty × 100, "a"],length 是101
let arr1 = [];
arr1[1.0000] = 'b';
console.log(arr1,arr1.length) // arr 是[empty, "b"],length 是2
~~~
#### 2、稀疏數組
> 稀疏數組就是包含從0開始的不連續索引的數組。通常數組的length屬性值代表數組中元素的個數。如果數組是稀疏的,length屬性值大于元素的個數
足夠稀疏的數組通常在實現上比稠密的數組更慢,更耗內存,在這樣的數組中查找元素所用的時間就變得跟常規對象的查找時間一樣長了,失去了性能的優勢。
~~~
let a1 = [,,]; // 數組直接量,該數組是[empty × 2]
0 in a1 // false: a1在索引0處沒有元素
let a2 = new Array(3); //[empty × 3],該數組根本沒有元素
0 in a2 // false: a2在索引0處沒有元素
let a3 = [undefined];
0 in a3 // true: a3在索引0處有一個值為undefined的元素
let a4 = [,undefined];
0 in a4 // fasle: a4在索引0處沒有元素
1 in a4 // true: a4在索引1處有一個值為undefined的元素
console.log(a4[0],a4[1]) // undefined undefined,可見數組訪問返回undefined,可能是稀疏數組,也可能是數組元素為undefined
~~~
#### 3、類數組對象
> 擁有一個數值length屬性和對應非負整數屬性的對象看做一種類型的數組
數組跟類數組相比有以下不同:
1. 當有新元素添加到數組中時,自動更新length屬性
2. 設置length為一個較小值將截斷數組
3. 從Array.prototype中繼承了一些方法
4. 其類屬性為'Array'
JavaScript 數組有很多方法特意定義通用,因此他們不僅應用在真正的數組而且在類數組對象上都能正確工作,JavaScript權威指南一書說的是:ES5中所有的方法都是通用的,ES3中除了toString()和toLocaleString()意外所有方法也是通用的。
類數組對象顯然沒有繼承自Array.prototype,所以它們不能直接調用數組方法,不過可以間接地使用Function.call方法調用。
~~~
// 類數組應用通用方法
let arrayLike = {0: 'name', 1: 'age', 2: 'address', length: 3 }
Array.prototype.join.call(arrayLike,'*') // "name*age*address"
// 還記得當初獲取的DOM元素怎么轉化成數組么?
functon toArray (DOM) {
return Array.prototype.slice.call(DOM);
}
//對的,這樣也可以的
let htmlCollection = document.getElementsByTagName('h2');
let arr1 = Array.prototype.map.call(htmlCollection,function (ele,index){return ele});
console.log(Array.isArray(arr1)) // true
// 還有這樣
let arrayLike = {0: 'name', 1: 'age', 2: 'address', length: 3 }
let arr2 = Array.prototype.concat.apply([],arrayLike);
console.log(arr) //["name", "age", "address"]
// ES6現在這樣
let arrayLike = {0: 'name', 1: 'age', 2: 'address', length: 3 }
let arr3 = Array.from(arrayLike);
console.log(arr3) // ["name", "age", "address"]
~~~
#### 4、 JavaScript數組的進化——類型化數組的引入
先說一下普遍意義上的Array,數組是一串**連續**的內存位置,用來保存某些值。JavaScript 中的數組是哈希映射,可以使用不同的數據結構來實現,如鏈表,上一個元素包含下一個元素的引用。這樣其他語言中數組的取值是根據內存位置進行數學計算就能找到,而在JavaScript中就需要遍歷鏈表之類的結構,數組越長,遍歷鏈表跟數據計算相比就越慢。
現代 JavaScript 引擎是會給數組分配連續內存的 —— 如果數組是同質的(所有元素類型相同)。所以在寫代碼時保證數組同質,以便 JIT(即時編譯器)能夠使用 c 編譯器式的計算方法讀取元素是一種優雅的方式。
不過,一旦你想要在某個同質數組中插入一個其他類型的元素,JIT 將解構整個數組,并按照舊有的方式重新創建。
ES6 增加了 ArrayBuffer, 提供一塊連續內存供我們隨意操作。然而,直接操作內存還是太復雜、偏底層。于是便有了處理 ArrayBuffer 的視圖(View)。
`ArrayBuffer`對象用來表示通用的、固定長度的原始二進制數據緩沖區。ArrayBuffer 不能直接操作,而是要通過類型數組對象或 DataView 對象來操作,它們會將緩沖區中的數據表示為特定的格式,并通過這些格式來讀寫緩沖區的內容。
~~~
語法: new ArrayBuffer(length)
參數
length:要創建的 ArrayBuffer 的大小,單位為字節。
返回值:一個指定大小的 ArrayBuffer 對象,其內容被初始化為 0。
異常:如果 length 大于 Number.MAX_SAFE_INTEGER(>= 2 ** 53)或為負數,則拋出一個 RangeError 異常。
~~~
`類型數組對象`一個TypedArray 對象描述一個底層的二進制數據緩存區的一個類似數組(array-like)視圖。事實上,沒有名為 TypedArray的全局對象,也沒有一個名為的 TypedArray構造函數。相反,有許多不同的全局對象,下面會列出這些針對特定元素類型的類型化數組的構造函數。
~~~
new TypedArray(); // ES2017中新增
new TypedArray(length);
new TypedArray(typedArray);
new TypedArray(object);
new TypedArray(buffer [, byteOffset [, length]]);
TypedArray()指的是以下的其中之一:
Int8Array();//8位二進制帶符號整數 -2^7~(2^7) - 1,大小1個字節
Uint8Array();//8位無符號整數 0~(2^8) - 1,大小1個字節
Int16Array();//16位二進制帶符號整數 -2^15~(2^15)-1,大小2個字節
Uint16Array();//16位無符號整數 0~(2^16) - 1,大小2個字節
Int32Array();// 32位二進制帶符號整數 -2^31~(2^31)-1,大小4個字節
Uint32Array();//32位無符號整數 0~(2^32) - 1,大小4個字節
Float32Array();//32位IEEE浮點數,大小4個字節
Float64Array(); //64位IEEE浮點數,大小8個字節
~~~
應用:
~~~
var buffer = new ArrayBuffer(8);
var view = new Int32Array(buffer);
view[0] = 100;
console.log(view)// [100,0],一個八個字節,Int32Array一個元素大小是4個字節,所以只能放下兩個元素
~~~
## 摘自
[JavaScript數組的十八般武藝](https://segmentfault.com/a/1190000015908109)