Array
寫之前鞏固一下JS的七種資料型別:number, string, boolean, null, undefined, symbol, object,
由此可見, Array屬於object.
Array
是JS的原生物件, 同時也是一個建構函式.
建構函式
var arr = new Array(2); // 生成一個兩個成員的陣列,每個位置都是空值
//等同於
var arr = Array(2);
複製程式碼
Array
建構函式有個很大的缺陷, 就是不同的引數, 會導致不一致性,比如:
var arr = new Array(2); // 第一個引數2代表陣列的length
var arr = new Array(2,2); // 第一個引數2代表陣列的第一個元素
var arr = new Array(); // 返回一個空陣列
var arr = new Array('abc'); // 返回一個陣列['abc']
複製程式碼
因此,通常建立陣列的時候,不建議使用建構函式建立, 使用陣列字面量最好:
var arr = [1,2];
複製程式碼
遍歷
// 下面是兩個陣列 arr 和 obj
var arr = [1,2]; // 記憶體中 __proto__, 指向的是Array.prototype
var obj = {0:1, 1:2, 'length':2}; // 記憶體中 __proto__, 指向的是Object.prototype
// 遍歷arr
for(let i = 0; i < arr.length; i++){
console.log(i, arr[i])
}
// 0 1
// 1 2
// 遍歷obj
for(let i = 0; i < obj.length; i++){
console.log(i, obj[i])
}
// 0 1
// 1 2
obj.xxx = 'xxx';
// 得到obj為
obj = {0:1, 1:2, 'length':2, xxx:"xxx"}
// 再次遍歷obj得到
// 0 1
// 1 2
// 換一種方法遍歷
for(let key in obj){
console.log(key, obj[key])
}
// 0 1
// 1 2
// 2 3
// length 3
// xxx xxx
複製程式碼
由上面的例子可以總計出:
- 所以遍歷是是遍歷, 和是不是陣列無關, 有關的是有沒有下標.
- 陣列之所以為陣列, 是因為你覺得他是陣列, 覺得是陣列就使用
for(let i = 0;i<obj.length;i++)
進行遍歷, 覺得不是就使用for(let key in obj)
遍歷. - 陣列本質: proto(原型)指向了
Array.prototype
. - 偽陣列:原型鏈中____proto___沒有指向Array.prototype;(例如:上面的obj,arguments)
靜態方法
Array.isArray
方法返回一個bool值, 表示引數是否為陣列.
var arr = [1,2,3];
typeof arr // 'object'
Array.isArray(arr) // true
複製程式碼
例項方法
講例項方法之前,先看下Array
建立之後的記憶體圖:
- valueOf(), toString()
所有物件都擁有的兩個公用方法.
var arr = [1,2,3];
arr.valueOf(); // [1,2,3]
arr.toString(); // "1,2,3"
複製程式碼
- push(), pop()
push
向陣列新增一個或者元素, pop刪除陣列的最後一個元素, 兩個方法都會改變原陣列
var arr = ['a', 'b', 'c'];
arr.push(1)
arr.push('d')
arr.push(true)
arr // ['a', 'b', 'c', 1, 'd', true]
var arr = ['a', 'b', 'c']
arr.pop() // ['a', 'b']
複製程式碼
push和pop結合使用, 構成了後進先出的stack結構.
- shift(), unshift()
shift
刪除陣列的第一個元素, unshift在陣列第一個位置新增元素, 兩個方法都會改變原陣列
var arr = ['a', 'b', 'c'];
a.shift() // ['b', 'c']
// 使用shift可以清空一個陣列
var arr = ['a', 'b', 'c'];
a.unshift('x', 'd') // ['x', 'd', 'a', 'b', 'c']
複製程式碼
shift和unshift結合使用, 構成了先進先出的queue結構.
- join()
join
陣列元素之間用指定引數作為分隔符拼接
var arr = [1,2,3];
arr.join(',') // "1,2,3"
arr.join() // "1,2,3" 不加引數,預設用逗號拼接
arr.toString(arr) // "1,2,3" 與join不同, 只是巧合
arr + "" // "1,2,3" 與join不同, 只是巧合
複製程式碼
- concat()
concat
拼接兩個陣列,生成一個新陣列, 原陣列不變
var a = [1,2,3];
var b = [4,5,6];
a.concat(b) // [1,2,3,4,5,6]
a.concat([]) // [1,2,3]
a.concat([]) !== a
複製程式碼
- reverse()
reverse
顛倒排列陣列元素 , 改變原陣列
var arr = [1,2,3];
arr.reverse(); // [3,2,1]
複製程式碼
- sort()
sort
對陣列成員進行排序, 快速排序方法, 需要接受一個函式, 函式返回排序依據, 改變原陣列
var a = [1,3,6,2,5];
a.sort(function(x,y){ return x-y }) // [1,2,3,5,6] 如果函式返回值小於等於0, 第一個元素排在第二個元素前面
a.sort(function(x,y){ return y-x }) // [6,5,3,2,1] 如果該函式的返回值大於0,表示第一個成員排在第二個成員後面
var students = ['小明','小紅','小花'] ;
var scores = { 小明: 59, 小紅: 99, 小花: 80 };
students.sort(function(x,y){
return scores[x] - scores[y]
})
複製程式碼
- map()
map
將所有元素依次傳入引數函式, 並將每一次的執行結果組成一個新陣列返回, 不改變原陣列.
var a = [1, 2, 3];
a.map(function(n){
return n + 1''
}) // [2, 3, 4]
複製程式碼
- forEach()
forEach
和map
方法相似, 也是對陣列的所有成員依次執行引數函式, 但是forEach
不會有返回值,只用來運算元據.
// forEach 有三個引數, 通常只寫兩個引數
1. 當前值
2. 當前位置
3. 陣列本身
var out = [];
[1, 2, 3].forEach(function(elem) {
this.push(elem * elem);
}, out); // 其中this 就是[1,2,3], 第一個引數是一個函式, 第二個引數是空陣列out, 回撥函式內部的this指向了out
out // [1, 4, 9]
複製程式碼
- filter()
filter
過濾陣列元素, 它的引數是一個函式,所有陣列成員依次執行該函式,返回結果為true
的成員組成一個新陣列返回。該方法不會改變原陣列。
var a = [1,2,3,4,5,6];
a.filter(function(value){
return value % 2 === 0
})
// [2,4,6]
a.filter(function(value,index){
return index % 2 !== 0
})
// [1,3,5]
複製程式碼
- reduce()
reduce
方法依次處理陣列的每個成員,最終累計為一個值.下面是四個引數:
- 累積變數,預設為陣列的第一個成員
- 當前變數,預設為陣列的第二個成員
- 當前位置(從0開始)(可選)
- 原陣列 (可選)
var a = [1,2,3,4,5];
a.reduce(function(a,b){
console.log(a,b);
return a+b;
})
// 15
複製程式碼
- 使用
reduce
表示map
var a = [1,2,3];
a.reduce(function(arr,n){
arr.push(n*2);
return arr;
},[])
// [2,4,6]
複製程式碼
- 使用
reduce
表示filter
var a = [1,2,3,4,5,6];
a.reduce(function(arr,n){
if(n % 2 === 0){
arr.push(n)
}
return arr
}, [])
// [2, 4, 6]
複製程式碼