由於在工做當中,常用到js的數組,而其中對數組方法的使用也是很頻繁的,因此老是會有弄混或者概念不夠清晰的情況,因此,寫下這篇文章整理一番,本文有對幾乎全部數組的方法的介紹,此外還有很是實用的一些數組操做好比亂序去重和斐波那契數列求值等等,總之乾貨滿滿~~javascript
//instanceof 測試某個對象是否由某個指定的構造器建立 [1,2,3] instanceof Array //true "1" instanceof Array // false //比instanceof更可靠 Array.isArray Array.isArray([1,2,3]); //true //Object對象的toString()方法,能夠返回所建立對象的內部類名 Object.prototype.toString.call([1,2,3]); //"[object Array]" Object.prototype.toString.call("a"); //"[object String]"
const test = [1,2,3]; test.toString(); //"1,2,3" test.valueOf(); //[1,2,3] //toLocaleString大部分爲返回與toString相同的結果,區別之處在於會調用每一項的toLocaleString()方法 test.toLocaleString([1,2,3]); //[1,2,3]; const testStr = test.join("|"); //"1|2|3" testStr.split("|"); // [1,2,3];
const test = new Array(); const count= test.push("a","b"); //count爲操做完後的數組長度 console.log(count); //2 const count1 = test.push("c"); console.log(count1); //3 const item = test.pop(); console.log(item); //"c"
const test = [1,2,3]; const item = test.shift(); console.log(item); //1 console.log(test); //[2,3];
const test = [1,2,3]; const test1 = test.reverse(); // [3,2,1] test1.sort(); //[1,2,3]
//concat會建立當前數組的一個副本再進行操做,不影響原數組 const test = [1,2,3]; const test1 = [1,2,3].concat([4,5]); console.log(test); //[1,2,3] console.log(test1); //[1,2,3,4,5] //slice接受一個或兩個參數,返回起始和結束位置之間的項(但不包括最後位置的項),不影響原數組 const test = [1,2,3,4]; const test1 = test.slice(0); //[1,2,3,4] const test2 = test.slice(1,3); //[2,3] console.log(test); //[1,2,3,4] 原數組未改變 //splice 可用做刪除、插入和替換,改變原數組 const test = [1,2,3,4,5]; test.splice(1,2); //test爲[1,4,5] test.splice(1,0,"a","b"); //test爲[1,"a","b",2,3,,4,5] test.splice(2,1,"c"); //test爲[1,2,"c",4,5]
const test = [1,2,3,4,5,4,3,2]; test.indexOf(4); //3 test.lastIndexOf(4); //5 test.indexOf("4"); //-1 必須全相等(===)
1.filter() 對數組的每一項容許給定函數,返回該函數會返回true的項組成數組,不會改變原數組html
const test = [1,2,3,4,5]; const test1 = test.filter((item) => item > 3); console.log(test); //[1,2,3,4,5]; console.log(test1); //[4,5];
2.map() 對數組的每一項執行給定函數,返回每次函數調用的結果組成的數組,不會改變原數組java
const test = [{a:1,b:2},{a:3,b:4},{a:5,b:6}]; const test1 = test.map((item) => item['a']); console.log(test); //[{a:1,b:2},{a:3,b:4},{a:5,b:6}] console.log(test1); //[1,3,5]
3.forEach 對數組的每一項運行給定函數,沒有返回新數組,沒有返回值node
const test = [[1],[2]]; test.forEach((item) => item.push(1)); console.log(test); //[[1,1], [2,1]]
1) 普通for循環(性能較好)
const test = [1,2,3,4]; for(let i=0,len=test.length;i<len;i++) { console.log(test[i]); } //1 //2 //3 //4
2) for in 以【任意】順序遍歷一個對象的可枚舉屬性,因此不太建議用來遍歷一個數組,緣由以下。
for...in不該該用於迭代一個 Array,其中索引順序很重要。數組索引只是具備整數名稱的枚舉屬性,而且與通用對象屬性相同。不能保證for ... in將以任何特定的順序返回索引。for ... in循環語句將返回全部可枚舉屬性,包括非整數類型的名稱和繼承的那些,即它返回的除了數字索引外還有多是你自定義的屬性名字。
const person = {work:"coder",age:"24",sex: "female"}; for(prop in person) { console.log(`Jchermy[${prop}]=${person[prop]}`); } //Jchermy[work]=coder //Jchermy[age]=24 //Jchermy[sex]=female
3)for..of
語句在可迭代的對象上建立了一個循環(包括Array, Map, Set, 參數對象( arguments) 等等),
對值的每個獨特的屬性調用一個將被執行的自定義的和語句掛鉤的迭代。
for..of 做爲es6中引進的循環,主要是爲了補全以前for循環中的如下不足 :
而相比之下for...of能夠作到:
let test = [3, 5, 7]; test.foo = "hello"; for (let i in test) { console.log(i); // "0", "1", "2", "foo" } for (let i of test) { console.log(i); // "3", "5", "7" // 注意這裏沒有 hello }
從以上咱們能夠看出for..of和for...in的區別 1. for...in循環出的是key,for...of循環出的是value 2. 做用於數組的for-in循環除了遍歷數組元素之外,還會遍歷自定義屬性,好比例子中的foo屬性。for...of循環不會循環對象的key,只會循環出數組的value。
4)do...while 語句一直重複直到指定的條件求值獲得假(false)es6
let i = 0; do { i += 1; console.log(i); } while (i < 5); //1 //2 //3 //4 //5
5) while只要指定的條件爲真就會一直執行它的語句塊算法
let n = 0; let x = 0; while(n<3) { n++; x +=n; console.log(n,xhdf); } // 1 1 // 2 3 // 3 6
將一個數組徹底打亂,而後返回打亂後的數組。也稱爲洗牌算法。數組
1) 利用Math.random()和sort()結合緩存
const test = [1,2,3,4]; test.concat().sort(()=> Math.random() - 0.5); // [2, 4, 1, 3]
這個方法貌似能夠實現咱們要的結果,可是實際上它並不徹底是隨機的,而是越大的數字出如今越後面的機率越大。具體緣由能夠看這篇文章數組的徹底隨機排列dom
2) 遍歷原數組,而後隨機產生下標,將這個下標的值push到新的數組中,並隨即刪除這值,注意不是用delete,那樣並不會改變數組的長度,效率不高,使用splice較好.函數
function shuffle(array) { let i,n=array.length,copy=[]; while(n) { i = Math.floor(Math.random()*n--);//n--是先與Math.random相乘再減一 copy.push(array.splice(i, 1)[0]); } return copy; } const test = [1,2,3,4,5]; console.log(shuffle(test)); //[2, 5, 4, 3, 1]
3)Fisher–Yates shuffle 算法 隨機從數組中抽出一個元素,而後與最後個元素交換,至關於把這個隨機抽取的元素放到了數組最後面去,表示它已是被隨機過了,同時被換走的那個元素跑到前面去了,會在後續的重複操做中被隨機掉。一輪操做事後,下一輪咱們只在剩下的n-1個元素也就是數組的前n-1個元素中進行相同的操做,直到進行到第一個。
function shuffle(array) { let i, n=array.length; while(n) { i = Math.floor(Math.random()*(n--)); t = array[i] array[i] = array[n]; array[n] = t; n--; } return array; } var test = [1,2,3,4]; console.log(shuffle(test.concat()));//傳入數組的副本
ps:這一題的解法有不少種,如下僅列出幾種
1) 首先祭出最經典的解法,利用遞歸求值。
function fibonacci(n) { if(n==0 || n==1 ) { return n; } return fibonacci(n-1)+fibonacci(n-2); } const test = fibonacci(4); //3
這種方法的問題是不少值會從新求值,效率很低,所以並不推薦。
2)利用ES6的解構賦值
const fibonacci =(n)=>{ let a = 0; let b= 1; let i = 2; while(i++ <= n){ [a, b] = [b, a+b]; //解構賦值 } return b; } fibonacci(4); //3
3) 尾遞歸優化
遞歸很是耗內存,由於須要同時保存成千上百個調用幀,很容易發生‘棧溢出’。但對於尾遞歸優化來講,因爲只存在一個調用幀,因此永遠不會發生棧溢出。而尾遞歸的實現,每每須要改寫遞歸函數,確保最後一步只調用自身。作到這一點的方法,就是把全部用到的內部變量改寫成函數的參數.
function fibonacci(n, n1=0, n2=1){ if(n <=1) { return n2; } return fibonacci(n-1, n2, n1 + n2); } fibonacci(6); //8
4)利用緩存值減小重複求值
function fibonacci(){ var cache = { 0:0, 1:1 } return function _fibonacci(n) { return typeof cache[n] === 'number' ? cache[n]: cache[n] = _fibonacci(n-1) + _fibonacci(n-2); } } const f = fibonacci(); f(9); //34
1)最經常使用的利用sort()排序,僅適用於純數字數組
//升序 function asc(arr){ return arr.sort((a,b)=> {return a-b;}) } asc([6,3,4,2]);//[2,3,4,6] //降序 function desc(arr){ return arr.sort((a,b)=> {return b-a;}) } desc([4,3,2,5]); //[5, 4, 3, 2]
2)由對象組成的數組,支持根據對象的某個屬性排序
const sortByProp = (name)=>{ return (f, s) => { var a, b; if (typeof f === 'object' && typeof s === 'object' && f && s) { a = f[name]; b = s[name]; if(a === b) { return 0; } else { return a < b ? -1 :1; } } else { throw new TypeError('數組必須由對象組成'); } }; }; const test = [{age:27, name:"xiaomi"},{age:17, name:"amy"},{age: 24, name: "Jchermy"}]; test.sort(sortByProp("age")); //[{age:17, name:"amy"},{age: 24, name: "Jchermy"}, {age:27, name:"xiaomi"}];
1)利用array_filter()
function unique(arr){ let uniqueArr = []; uniqueArr = arr.filter((item) =>{ return uniqueArr.includes(item) ? '' : uniqueArr.push(item); }) return uniqueArr; }; unique([1,2,3,1,6,3,2,7]); //[1,2,3,6,7];
2)利用es6中的Map()
function unique(arr) { const seen = new Map(); return arr.filter((item) => !seen.has(item) && seen.set(item, 1)); } unique([11,2,3,4,4,2,5]); //[11, 2, 3, 4, 5]
3)利用es6中的Set()
function unique(arr){ return [...new Set(arr)]; //將set結構轉爲數組 } unique([1,2,2,3,7,3,8,5]); //[1, 2, 3, 7, 8, 5]
function filter_array(array) { return array.filter(item=>item); } const test = [undefined,undefined,1,'','false',false,true,null,'null']; filter_array(test); //[1, "false", true, "null"]
呼,寫了好幾天的文章終於寫完啦,撒花~~🌹 若是你看到這裏,以爲對你有所幫助的話,歡迎點贊收藏呀😁😁固然也很是歡迎你們對有紕漏的地方進行指正和建議,我必定會虛心接受的!但願你們能一塊兒學習進步!