關於數組這一塊,從開始寫項目開始就一直在用,可是基本都沒有整理過,怎麼說呢?既然在複習這個東西,那我今天正好在複習這個數組,就集中整理一下在實際開發中用到頻率最高的數據吧。前端
es5中定義了22個數組的方法,這22個方法的使用頻率基本貫穿整個前端開發,若是你想進入前端,這22個應該成爲你的本能反應。下面就針對這22個,我來簡單作一下代碼的實例吧:es6
關於數組定義通常有兩種方式:數組
具體的定義以下:bash
var testArray = new Array();
var testArray1 = [1,2,3,4,5];
複製代碼
額,這裏重點提一下數組的清空,我建議使用:函數
var testArray = [];
複製代碼
在es5裏面檢測數據類型是否是數組的方式主要有兩個,length主要用來獲取數組的長度:ui
具體的代碼以下:this
var array = [1,2,3,4,5];
var object = { key:1,value:"hello"};
console.log(array instanceof Array); // true
console.log(object instanceof Array); // false
console.log(Array.isArray(array)); // true
console.log(Array.isArray(object)); // false
console.log(array.length) // 5
複製代碼
數據轉化成字符串通常有三種方式:編碼
來看下面一段代碼:es5
console.log(array.toString()); // 1,2,3,4,5
console.log(array.toLocaleString()); // 1,2,3,4,5
console.log(array.join("")); // 12345
console.log(array.join("&&")); // 1&&2&&3&&4&&5
console.log(array.join()); // 1,2,3,4,5
複製代碼
首先toString和toLocaleString是將數組直接轉化成String,中間用逗號分隔。(到如今爲止我都不知道二者在Array中有什麼區別,我本身作實驗只在Date中發現了一點異常。)spa
其次是join:數組元素先被轉換爲字符串,再將這些字符串用 separator 分割鏈接在一塊兒。若是沒提供分隔符,將一個逗號用做分隔符。
數組的增刪操做的屬性一共下面幾種:
來看下面一段代碼:
var array = [1,2,3,4,5];
array.push(999); // [ 1, 2, 3, 4, 5, 999 ]
array.pop(); // [ 1, 2, 3, 4, 5 ]
array.unshift(999); // [ 999, 1, 2, 3, 4, 5 ]
array.shift(); // [ 1, 2, 3, 4, 5 ]
複製代碼
關於數組的排序,主要有兩個方法:
var array = [1,2,3,4,5];
array.reverse(); // [ 5, 4, 3, 2, 1 ]
複製代碼
sort方法接收兩個參數,第一個是數組,第二個參數若是存在,就會按照第二個函數的返回值來排序,若是不存在 缺省值是從小到大。來看下面一段代碼:
array.sort() // [ 1, 2, 3, 4, 5 ]
array.sort((a,b)=>{
return b-a;
});
console.log(array); // [ 5, 4, 3, 2, 1 ]
複製代碼
關於數組的排序這一塊的源碼呢,以前我有看過一部分,我發現,在源碼中數組長度小於23的時候採用的是插入排序,反之則用的是快速排序。(甚至命名都是InsertionSort,QuickSort),關於排序的實現方式,能夠去看一下 我以前寫的排序的文章來複習一下,我以爲我本身寫的還比較好理解的。
var array1 = [1,2,3];
var array2 = ["1","2","3"];
console.log(array1.concat(array2)); // [1,2,3,"1","2","3"];
複製代碼
var arr = [1, 2, 3, "a", "b", "c"];
console.log(arr.slice(3)); //["a", "b", "c"]
console.log(arr.slice(0,3)); // [1, 2, 3]
console.log(arr.slice(0,10)); // [1, 2, 3, "a", "b", "c"]
console.log(arr.slice(7,10)); //[]
console.log(arr.slice(-2)); // ["b", "c"]
console.log(arr.slice(3,0)); // []
console.log(arr); //
複製代碼
這裏值得咱們注意的點是: 一、 slice默認接收兩個參數,slice(start,end),表示從開始截取的位置和截取結束的位置。 二、 若是隻填寫一個參數,是從該位置開始向後截取,直到末尾。 三、 若是隻填寫一個負數參數的話,是從末尾開始向前截取。 四、 若是第一個參數比後面大,返回值爲空數組。 五、 若是截取的開始位置大於數組長度返回空數組。 六、 若是截取的結束位置大於數組的長度,返回開始截取到數據的末尾的數列。
首先來看一個基礎的例子
var arr = [1, 2, 3, "a", "b", "c"];
arr.splice(2);// [ 1, 2 ]
arr.splice(0,1); // [2]
複製代碼
而後咱們再來看一個帶插入的例子:
var arr1 = [1, 2, 3, "a", "b", "c"];
arr1.splice(3,2,"hello","world");// [ 1, 2, 3, 'hello', 'world', 'c' ]
複製代碼
值得咱們注意的點是: 一、 splice的參數含義是:splice(開始操做的索引值,刪除幾項,後面的n項表明從開始操做的索引值開始插入的項) 二、 若是隻傳入一個參數,默認返回0到指定參數的值
var arr = [1, 2, 3, "a", "b", "c"];
console.log(arr.indexOf("b")); // 4
console.log(arr.lastIndexOf("b")); // 4
console.log(arr.indexOf("es")); // -1
複製代碼
這裏值得注意的是:indexOf是去查詢元素第一次出現的索引,而lastIndexOf是去查詢元素最後一次出現的索引。
var arr = [ 1, 2, 3, 4, 5 ];
arr.every((item,index,array)=>{
if(item>0) return true;
return false;
}); //true
arr.every((item,index,array)=>{
if(item>3) return true;
return false;
}); // false
複製代碼
從上面的代碼,咱們能夠看出: 一、 every接收一個函數,函數的返回參數有三個,遍歷的項,當前遍歷的index和數組自己 二、 當函數的所有項都返回true的時候every才成立;有一項不返回true,every將不會成立。
var arr = [ 1, 2, 3, 4, 5 ];
arr.some((item,index,array)=>{
if(item>4) return true;
return false;
}); //true
arr.some((item,index,array)=>{
if(item>7) return true;
return false;
}); // false
複製代碼
從上面的代碼,咱們能夠看出 一、 some接收一個函數,函數的返回參數有三個,遍歷的項,當前遍歷的index和數組自己 二、 當函數的所有項都返回false的時候some就會返回false;有一項返回true,some都將成立。
var arr = [ 1, 2, 3, 4, 5 ];
arr.filter((item,index,array)=>{
return item>3;
}); //[ 4, 5 ]
複製代碼
從上面能夠看出來,filter將會篩選出知足條件的數列出來。
var arr = [ 1, 2, 3, 4, 5 ];
arr.map((item,index,array)=>{
if(item>3){
return {key:"小於三的數",value:item}
}
return {key:"大於二的數",value:item}
});
//[ { key: '大於二的數', value: 1 },
// { key: '大於二的數', value: 2 },
// { key: '大於二的數', value: 3 },
// { key: '小於三的數', value: 4 },
// { key: '小於三的數', value: 5 } ]
複製代碼
從上面咱們能夠得出,map方法是將每一項的返回值從新組裝成一個新的數組,若是沒有return會返回。
var arr = [ 1, 2, 3, 4, 5 ];
var result1 = arr.reduce((sum,item)=>{
return sum*10 + item;
});
var result2 = arr.reduceRight((sum,item)=>{
return sum*10 + item;
});
console.log(result1)
console.log(result2)
複製代碼
關於from和of,其實可能遇到call和bind,能夠看看以前個人文章。
var obj = {
"0":"a",
"1":"b",
"2":"c",
length: 3
}
var obj1 = {
"0":"a",
"1":"b",
"2":"c",
}
var obj2 = {
"a":"a",
"b":"b",
"c":"c",
length: 3
}
console.log(Array.from(obj)); // [ 'a', 'b', 'c' ]
console.log(Array.from(obj1)); // []
console.log(Array.from(obj2)); // [ undefined, undefined, undefined ]
複製代碼
從上面的代碼,咱們能夠清楚的發現: 一、 Array.from是須要length屬性的,若是沒有length屬性,將返回空數組 二、 Array.from操做對象的屬性名必定是數字,否則會返回undefined。
Array.of主要用於將一組值轉化成數組
Array.of(3, 11, 8) // [3,11,8]
Array.of(3) // [3]
Array.of(3).length // 1
複製代碼
Array.of的建立主要是爲了彌補Array方法的一些小漏洞,例如:
Array() // []
Array(3) // [, , ,]
Array(3, 11, 8) // [3, 11, 8]
複製代碼
fill方法的做用是,將給的定值填充到數組中,來看下面一組代碼:
['a', 'b', 'c'].fill(7); // [7, 7, 7]
new Array(3).fill(7) // [7, 7, 7]
['a', 'b', 'c'].fill(7, 1, 2) // ['a', 7, 'c']
let arr = new Array(3).fill({name: "jkb"});
arr[0].name = "klivitam";
console.log(arr); // [{name: "klivitam"}, {name: "klivitam"}, {name: "klivitam"}]
複製代碼
從上面的代碼咱們能夠發現: 一、 fill接收三個參數,fill(填充的值,填充的開始值,填充的結束值) 二、當只存在一個參數時,默認將所有數組都填充給列表項 三、 當填充的值是對象的時候,咱們是填充的對象的指針,因此這是一個坑 在用的時候請謹慎哦。
let data = [1,2,3,4,5];
let obj = {
name:"klivitam",
number:1
}
let result1 = data.find((it,index,arr)=>{
return it>3;
})
let result2 = data.findIndex((it,index,arr)=>{
return it>3;
})
let result3 = data.find((it,index,arr)=>{
return it>10;
})
let result4 = data.find(function(v){
return v>this.number;
},obj)
console.log(result1) // 4
console.log(result2) // 3
console.log(result3) // undefined
console.log(result4) // 2
複製代碼
從面的代碼咱們能夠發現: 一、 find和findIndex分別都接收兩個參數,第一個是函數,第二個是對象,前一個函數的this指針指向後一個對象 二、 find和findIndex只能發現數組內出現的第一個值,若是沒有發現返回undefined
let data = [1,2,3,4,5,NaN];
console.log(data.includes(1)); // true
console.log(data.includes(1,2)) // false
console.log(data.includes(NaN)) // true
console.log(data.indexOf(NaN)) // -1
複製代碼
從面的代碼咱們就能夠清楚的發現: 一、 includes方法接收兩個參數,第一個是搜索的值,第二個是從數據的第幾項開始搜索 二、 indexOf沒法查找到NaN的位置,可是includes能夠。
let data = [1,2,3];
for (let index of data.keys()) {
console.log(index);
}
// 0
// 1
// 2
for (let elem of data.values()) {
console.log(elem);
}
// 1
// 2
// 3
//這裏使用瞭解構賦值
for (let [index, elem] of data.entries()) {
console.log(index, elem);
}
// 0 1
// 1 2
// 2 3
複製代碼
console.log(...[1, 2, 3]); // 1,2,3
console.log((...[1, 2,3])); // Uncaught SyntaxError: Unexpected number
Math.max(...[14, 3, 77]) // 77
const [...[1,2,3]] = a1; // 1,2,3
[...['a', 'b'], ...['c'], ...['d', 'e']]; // [a,b,c,d,e]
[...'hello'];// [h,e,l,l,0]
複製代碼
關於擴展運算符這一塊,我不想過多的來說解,其實不少東西 仍是要靠本身在寫代碼的時候來總結,關於有些技術,我也不知道哪裏好,可是遇到問題了 我就想用。
[1, 2, 3, 4, 5].copyWithin(0, 3); // [4, 5, 3, 4, 5]
// 將3號位複製到0號位
[1, 2, 3, 4, 5].copyWithin(0, 3, 4) // [4, 2, 3, 4, 5]
[1, 2, 3, 4, 5].copyWithin(0, -2, -1); // [4, 2, 3, 4, 5]
[].copyWithin.call({length: 5, 3: 1}, 0, 3)// {0: 1, 3: 1, length: 5}
複製代碼
從上面的代碼咱們能夠發現: 一、 數組實例的copyWithin方法,在當前數組內部,將指定位置的成員複製到其餘位置(會覆蓋原有成員),而後返回當前數組。也就是說,使用這個方法,會修改當前數組。 二、 該方法接受三個參數,分別是從該位置開始替換數據,從該位置開始讀取數據,到該位置前中止讀取數據。
[1, 2, [3, 4]].flat(); // [1, 2, 3, 4]
[1, 2, [3, [4, 5]]].flat(); // [1, 2, 3, [4, 5]]
[1, 2, [3, [4, 5]]].flat(2); // [1, 2, 3, 4, 5]
[1, [2, [3]]].flat(Infinity)// [1, 2, 3]
[1, 2, , 4, 5].flat() // [1, 2, 4, 5]
[2, 3, 4].flatMap((x) => [x, x * 2])// [2, 4, 3, 6, 4, 8]
複製代碼
從上面的代碼咱們能夠發現:
前面在講解flat的時候,咱們提到了一個空位的概念,結合開發以及阮大神在博客中的總結,我也更深的瞭解到空位的差別。 首先咱們來看一段代碼:
[,'a'].forEach((x,i) => console.log(i)); // 1
['a',,'b'].filter(x => true) // ['a','b']
[,'a'].every(x => x==='a') // true
[1,,2].reduce((x,y) => x+y) // 3
[,'a'].some(x => x !== 'a') // false
[,'a'].map(x => 1) // [,1]
[,'a',undefined,null].join('#') // "#a##"
[,'a',undefined,null].toString() // ",a,,"
複製代碼
這裏咱們就能夠明顯的看到在es5中對空格的處理方法就已經出現了分歧。
那咱們來看es6呢?來看下面一段代碼:
Array.from(['a',,'b'])// [ "a", undefined, "b" ]
[...['a',,'b']] // [ "a", undefined, "b" ]
[,'a','b',,].copyWithin(2,0) // [,"a",,"a"]
new Array(3).fill('a') // ["a","a","a"]
let arr = [, ,];
for (let i of arr) {
console.log(1);
}
// 1
// 1
[...[,'a'].entries()] // [[0,undefined], [1,"a"]]
[...[,'a'].keys()] // [0,1]
[...[,'a'].values()] // [undefined,"a"]
[,'a'].find(x => true) // undefined
[,'a'].findIndex(x => true) // 0
複製代碼
從上面代碼咱們能夠發現:
其實用代碼演示了這麼多,無非就是想說明一件道理:空位不一樣的方法對其的處理方式不一樣 若是你可以記得全部方法的處理方式,那你大能夠任意使用 若是不行 仍是儘可能避免出現空位吧
這篇文章寫的我非常煩躁呀,主要總結下來東西實在是太多了,可是怎麼說呢?仍是有很大的好處的,好比數組的空位這個以前我就只知道基礎的幾種,剩下的 我基本都沒有去驗證,如今抽時間把這些東西所有驗證了一遍感受印象也加深了很多。好了 差很少一點鐘了,去睡覺了 (說好的從這周起開始睡美容覺的)