JavaScript數組的使用小結(詳細仍是去看MDN)

JavaScript中的數組是一種特殊的對象,因爲對象的屬性必須是字符串的形式,因此數組的數字索引在內部被轉爲字符串類型。javascript

建立數組

1.0 直接用 []建立

數組中的元素能夠是不一樣的數據類型java

var arr1 = [1,2,3,4,"hello","adf",false]; // 數組中的元素能夠是不一樣的數據類型
console.log(arr1) //[ 1, 2, 3, 4, 'hello', 'adf', false ]
複製代碼

2.0 用Array對象建立

var arr2 = new Array(1,2,4,5,"abc",true)
console.log(arr2) //[ 1, 2, 4, 5, 'abc', true ]
複製代碼

Array構造函數有一個很大的缺陷,就是不一樣的參數,會致使它的行爲不一致。web

// 無參數時,返回一個空數組
new Array() // []

// 單個正整數參數,表示返回的新數組的長度
new Array(1) // [ empty ]
new Array(2) // [ empty x 2 ]

// 非正整數的數值做爲參數,會報錯
new Array(3.2) // RangeError: Invalid array length
new Array(-3) // RangeError: Invalid array length

// 單個非數值(好比字符串、布爾值、對象等)做爲參數,
// 則該參數是返回的新數組的成員
new Array('abc') // ['abc']
new Array([1]) // [Array[1]]

// 多參數時,全部參數都是返回的新數組的成員
new Array(1, 2) // [1, 2]
new Array('a', 'b', 'c') // ['a', 'b', 'c']
複製代碼

3.0 經過字符串的split()方法生成數組

var s = "i am a web coder i can say hello world!";
var arr3 = s.split(" "); // split()函數的參數是指定分隔符,而後經過分隔符分割字符串造成數組
console.log(arr3) //[ 'i', 'am', 'a', 'web', 'coder', 'i', 'can', 'say', 'hello', 'world!' ]
複製代碼

4.0 用已有的數組建立數組

4.0.1 經過數組拼接

concat拼接數組是生成了一個新的數組,原數組不發生變化數組

var a1 = [1,2,3];
var a2 = [4,5,6];
var a3 = a1.concat(a2); // 將a2中的元素按順序拼接到a1的元素後面並生成二者拼接的新數組
console.log(a1); //[ 1, 2, 3 ] a1沒有發生變化
console.log(a2); //[ 4, 5, 6 ] a2沒有發生變化
console.log(a3); //[ 1, 2, 3, 4, 5, 6 ] a1和a2的順序拼接
複製代碼

4.0.2 經過數組截取

splice截取數組,原數組會發生變化,可用來刪除數組中的元素app

var b1 = [1,2,3,4,5];
var b2 = b1.splice(3,3); // 將b1數組中的從索引3開始截取最多3個元素,而後將截取的子數組賦值給b2
console.log(b1); // [ 1, 2, 3 ] b1數組會發生改變,截去splice的部分
console.log(b2); // [ 4, 5 ] b2數組獲取splice(3,3)截取的子數組
複製代碼

5.0 ES6 建立數組的兩個API

5.0.1 Array.of

返回由全部參數值組成的數組,若是沒有參數,就返回一個空數組函數

var a = Array.of(1,2,3,4,5) // [1,2,3,4,5]
var b = Array.of(7) // [7]
複製代碼

5.0.2 Array.from

定義:用於將兩類對象轉爲真正的數組(不改變原對象,返回新的數組)。
參數:
第一個參數(必需):要轉化爲真正數組的對象。
第二個參數(可選): 相似數組的map方法,對每一個元素進行處理,將處理後的值放入返回的數組。
第三個參數(可選): 用來綁定this。測試

// 類數組是索引是 0 1 2 3... 而且有length屬性的對象
let obj = {0: 'a', 1: 'b', 2:'c', length: 3};
let arr = Array.from(obj); // ['a','b','c'];
複製代碼

增長數組元素

1.0 直接經過下標添加

經過數組索引添加,若添加的索引位置原來有值則更新原來的值,若沒有值則新建一個數組元素,若新建的元素與以前的數組元素不連續,則中間的數據位置保留併爲undefinedui

var a = [1,2,3];
a[a.length] = 4; //在末尾增長一個元素
console.log(a); // [ 1, 2, 3, 4 ]
a[10] = 10; //索引超過 a.length 也是能夠插入的,數組會保留前面沒有數據的位置
console.log(a); //[ 1, 2, 3, 4, <6 empty items>, 10 ]
console.log(a[8]); // undefined 保留的數據位置會設置爲 undefined
複製代碼

2.0 經過push在尾部添加

push能夠在數組的末尾添加1個或者多個元素,並返回添加完畢以後數組中元素的個數this

var b = [1,2,3];
var b_length = b.push(4);
console.log(b_length); // 4 push的返回值是添加完元素以後的數組長度
b.push(5,6); //能夠一次插入一個或者多個
console.log(b); // [ 1, 2, 3, 4, 5, 6 ]
複製代碼

3.0 經過unshift在數組頭部插入

unshift能夠在數組的頭部插入一個或者多個元素,並返回添加完畢以後數組中的元素個數spa

var c = [1,2,3];
var c_length = c.unshift(4);
console.log(c_length); // 4 unshift返回的值是添加玩元素以後的數組長度
c.unshift(5,6);
console.log(c); //[ 5, 6, 4, 1, 2, 3 ]
複製代碼

4.0 經過splice自由的插入元素

splice有3個元素, 第一個是索引,刪除或者添加的位置, 第二個是刪除的元素個數,第三個是添加的元素

splice有多個元素, 第一個固定爲索引,刪除或者添加的位置。第二個是刪除的元素個數,是 0 或者負數,則不移除元素。這種狀況下,至少應添加一個新元素。第三個以後則是添加進數組的元素

var d = ['a','b','c']
d.splice(3,0,4); // splice有3個元素, 第一個是索引,刪除或者添加的位置, 第二個是刪除的元素個數,第三個是添加的元素
console.log(d); // [ 'a', 'b', 'c', 4 ]
複製代碼

刪除數組元素

1.0 經過 pop 移除末尾的元素

pop移除數組最後一個元素並將其返回

var a = [1,2,3];
var tmp = a.pop(); // 返回值爲刪除的元素
console.log(tmp); // 3
console.log(a); // [1,2]
複製代碼

2.0 經過shift 移除頭部的元素

shift移除數組第一個元素並將其返回

var b = [1,2,3]; 
var tmp = b.shift(); // 返回值爲刪除的元素
console.log(tmp); // 1
console.log(b); // [2,3]
複製代碼

3.0 經過splice 刪除任意位置的元素

splice有3個元素, 第一個是索引,刪除或者添加的位置, 第二個是刪除的元素個數,第三個是添加的元素
在刪除數組元素的時候通常只用前兩個,指定刪除的索引發始位置和刪除的個數,並將刪除的元素按照子數組返回

var c = [1,2,3,4,5,6];
var tmp = c.splice(3,3); // 從索引3開始刪除最多3個元素,截取的元素按照數組的形式返回
console.log(tmp); //[4,5,6]
console.log(c); // [1,2,3]
複製代碼

查詢數組元素

1.0 經過indexOf查找

indexOf查詢是否包含指定的元素,若存在則返回索引,不存在返回-1

var a = ['a','b','c','d'];
var index1 = a.indexOf('a');
var index2 = a.indexOf('e');
console.log(index1); //0
console.log(index2); //-1
複製代碼

2.0 經過includes查找

查找數組中是否含有某個元素,存在返回true,不存在返回false

var index3 = a.includes("a");  // 存在返回true 不存在返回false
console.log(index3);
複製代碼

數組排序

使用sort函數

對於字符類型的數組,能夠直接用**sort()**函數按照Unicode碼升序排序,若是須要反序使用reverse()

var a = ['abc','hello','qwen','bob']; // 默認按照Unicode碼的順序排序
a.sort();
console.log(a); // [ 'abc', 'bob', 'hello', 'qwen' ]
console.log(a.reverse()); //[ 'qwen', 'hello', 'bob', 'abc' ]
var b = [1,100,12,3,4];
b.sort();
// sort()方法排序的時候默認排序的對象是字符串
// 因此在純數字排序的時候會將number類型轉成字符串類型進行排序
console.log(b); //[ 1, 100, 12, 3, 4 ]


// 數字排序的方法 經過給sort()傳入一個比較函數

function compare(num2,num1){
    /** * 升序排序 * 返回值大於0 表示交換位置 * 返回值小於0 表示不用交換 * 等於0 相等 */
    return num2 - num1;
}
b.sort(compare)
console.log(b) // [ 1, 3, 4, 12, 100 ]
複製代碼

數組的進階操做

1.0 join

使用join()拼接數組生成字符串,並返回這個字符串。其中join能夠接受一個符號用來拼接字符串,默認的狀況下爲直接串聯不添加任何拼接字符串。

var arr = [1,'a',true,'hello'];
var string1 = arr.join('-');
var string2 = arr.join();
console.log(string1) // 1-a-true-hello
console.log(string2); // 1atruehello
複製代碼

2.0 slice

slice(start,end)獲取原數組的部分做爲子數組返回,原數組不發生改變。截取的時候遵循左閉右開原則。

var a = [1,2,3,4,5,6,7];
var b = a.slice(0,5); // 包含start,不包含end 左閉右開
console.log(a); // [ 1, 2, 3, 4, 5, 6, 7 ] 原數組不發生改變
console.log(b); // [ 1, 2, 3, 4, 5 ]
複製代碼

3.0 map

map()建立一個新數組並返回,其中新數組的每一個元素由調用原始數組中的每個元素執行提供的函數獲得,原數組不發生改變

var a = [1,2,3,4,5,6];

function twoSize(item){
    return item * 2; //放大兩倍
}
var b = a.map(twoSize);
console.log(a); // [ 1, 2, 3, 4, 5, 6 ]
console.log(b); // [ 2, 4, 6, 8, 10, 12 ]

// 使用匿名函數

var c = a.map(function(item){
    return item * 3; // 放大三倍
});

console.log(c); //[ 3, 6, 9, 12, 15, 18 ]
複製代碼

4.0 every

對數組中的每一個元素都執行一次指定的回調函數,直到回調函數返回false,此時every()返回false並再也不繼續執行。若是回調函數對每一個函數都返回trueevery()函數也返回true

var a = [2,4,6,8,10];
var res1 = a.every(function(item){
    return item % 2 == 0;//判斷是否偶數
});
console.log(res1); //true

var res2 = a.every(function(item){
    return item % 2 != 0; //判斷是奇數
});// 在判斷第一個元素是否奇數的時候就返回了false,後面的再也不執行
console.log(res2); //false
複製代碼

能夠將every(func)函數當作判斷數組中的元素是否都知足func指定的規則,若所有知足返回true,如有一個不知足則再也不判斷返回false
操做相似於下面的截斷運算

var tmp3 = func(a[0])&&func(a[1])&&...&&func(a[n])
複製代碼

5.0 some

對數組中的每一個元素都執行一次指定的回調函數,直到回調函數返回true,此時some()返回true並再也不繼續執行。若是回調函數對每一個元素都返回false,那麼some()將返回false

var a = [1,2,3,4,5];
var res1 = a.some(function(item){
    return item % 2 == 0;//只要有一個爲偶數就返回true
});

console.log(res1); //true
複製代碼

能夠將some(func)函數當作判斷數組中的元素是否存在知足func指定的規則的元素,若存在知足的元素返回true,並再也不向後判斷,若所有不知足則返回false
操做相似於

var tmp3 = func(a[0]) || func(a[1]) ||...|| func(a[n])
複製代碼

6.0 filter

建立一個新的數組,包含經過全部提供函數實現的測試的全部元素。過濾數組。原數組不發生改變

var a = [1,2,3,4,5,6]
/* item:當前的遍歷值 index:當前的索引 self:數組對象 */
var res = a.filter(function(item,index,self){
    return item % 2 == 0;//返回全部偶數
});

console.log(res); // [ 2, 4, 6 ]
複製代碼

過濾數組,返回符合回調函數爲true的元素

7.0 forEach

針對每個元素執行提供的函數。會修改原來的數組,不會返回執行結果,返回undefined

var a = [1,2,3,4,5];
a.forEach(function(item, index){
    // return item * 2; //沒法直接擴大擴大兩倍
    a[index] = item * 2;
});
複製代碼

8.0 reduce

Array的reduce()把一個函數做用在這個Array[x1, x2, x3...]上,這個函數必須接收兩個參數,reduce()把結果繼續和序列的下一個元素作累積計算,其效果就是:

[x1, x2, x3, x4].reduce(f) = f(f(f(x1, x2), x3), x4)
複製代碼

案例1:求累加和

var a = [1,2,3,4,5];
function add(total,next){
    return total + next; // 每次的返回值會做爲下次調用add的total
}
var b = a.reduce(add);
console.log(b); // 15
複製代碼

案例2:求元素出現的次數

var words = ["apple","hello","orange","apple"];

var wordCount = function(prev,next){
    prev[next] = (prev[next] + 1) || 1; // 若是存在就加1,不然設置爲1
    return prev;
}

var obj = words.reduce(wordCount,{});
console.log(obj); // { apple: 2, hello: 1, orange: 1 }
複製代碼

對reduce的思考:
reduce(callback,initiaValue)會傳入兩個變量,回調函數(callback)和初始值(initiaValue)。若是不設置初始值,則第一次執行的時候,callback的第一個參數是數組的第一個元素,第二個參數是數組的第二個元素。有初始值則prev爲初始值,next爲數組第一個元素。

數組遍歷

1.0 length + for 循環

for(let i =0;i<arr.length;i++){
    console.log(i+":"+arr[i]);
}
複製代碼

2.0 使用forEach

forEach中的回調函數的兩個參數中值在前,索引在後

arr.forEach(function(val,index){
    console.log(index+":"+val);
});
複製代碼

3.0 for ... in

for...in的方式遍歷的是數組中的索引,前面也提到過數組是一種特殊的對象,在默認的狀況下是以0...n的數字做爲索引,可是也能夠用其餘字符做爲索引,因此當數組中存在其餘索引的時候能夠用for...in獲取

for(let index in arr){
    console.log(index+":"+arr[index]);
}
複製代碼

前面三種遍歷打印的值

/* 0:a 1:b 2:c 3:d */
複製代碼

4.0 for ... of

for ... of直接遍歷數組中的值

for(let val of arr){
    console.log(val);
}
/* a b c d */
複製代碼

5.0 for...in 和 for...of的區別

for … in循環,它遍歷的其實是對象的屬性名稱。
一個Array數組實際上也是一個對象,它的每一個元素的索引被視爲一個屬性。
當咱們手動給Array對象添加了額外的屬性後,for … in循環將帶來意想不到的意外效果:

var arr = ['a','b','c'];
arr.k = "hello";

for(let i in arr){
    console.log(i+":"+arr[i]); //遍歷的是屬性值
}
/* 0:a 1:b 2:c k:hello */
console.log(arr); // [ 'a', 'b', 'c', k: 'hello' ]
複製代碼

for ... of執行的時候,只遍歷值可是沒有去遍歷新加的k

var arr = ['a','b','c'];
arr.k = "hello";

for(let val of arr){
    console.log(val);
}
/* a b c */
複製代碼

詳細看:developer.mozilla.org/zh-CN/docs/…

兩個升序數組合爲一個升序數組

var arr1 = [1,6,7,8,9]
var arr2 = [2,3,4,5]

// 1.0 合併成一個數組而後排序
function compare(num1,num2){
    return num1 - num2;
}
var res = arr1.concat(arr2)
res.sort(compare);
console.log(res); //[ 1, 2, 3, 4, 5, 6, 7, 8, 9]


// 2.0 用兩個指針 i j 指向兩個數組的頭部依次比較插入

var i = 0;
var j = 0;
tmp = [];
while(i<arr1.length&&j<arr2.length){
    if(arr1[i]<=arr2[j]){
        tmp.push(arr1[i]);
        i++;
    }else{
        tmp.push(arr2[j]);
        j++;
    }
}
var res = tmp.concat(arr1.slice(i)).concat(arr2.slice(j)); //拼接沒有遍歷完的數組
console.log(res)
複製代碼

數組去重

// 1.0 用set去重 而後用 Array.from轉爲list
var myset = Array.from(new Set(arr));
console.log(myset); // [ 1, 2, 3, 4 ]

// 2.0 用reduce
function compare(num1,num2){
    return num1 - num2;
}
arr.sort(compare);//先排序
var res = arr.reduce(function(init,current){
    if(init.length===0||init[init.length-1]!=current){
        init.push(current);
    }
    return init;
},[]);
console.log(res); // [ 1, 2, 3, 4 ]

// 3.0 filter

var res = arr.filter(function(item,index,self){
    return self.indexOf(item) === index; //從前日後查找對應元素的索引是否與當前索引相等,要是不相等說明以前出現太重複的元素
});
console.log(res);
複製代碼

求兩個數組的交集

遍歷其中一個數組,而後用indexOf來判斷是否在另外一個數組中出現

var a = [1,2,3,4,4,5];
var b = [3,4,5,6,7];


// 1.0 用 indexOf
var res = []
for(let val of a){
    if(b.indexOf(val)!=-1){
        res.push(val);
    }
}
console.log(res); // [ 3, 4, 4, 5 ]
複製代碼

求只出現一次的數字

一個非空數組,其中只有一個元素只出現了一次,其他均出現兩次,找出那個只出現一次的數字

// 1.0 用reduce
// 用 reduce統計出現次數
var res = a.reduce(function(init,current){
    init[current] = (init[current] + 1) || 1;
    return init;
},{});
// 遍歷結果選出出現一次的元素
for(let i in res){
    if(res[i]==1){
        console.log(i);// 3
    }
}
複製代碼

兩數之和

給定一個整數數組和一個目標值,找出數組中和爲目標值的兩個數。須要考慮的是4-2=2這時候數組中必須有兩個2
暴力方法

var arr = [1,2,3,5,9];
var target = 7;
// 暴力遍歷 假設只有一組數相加爲

for(let i=0;i<arr.length;i++){
    for(let j=i+1;j<arr.length;j++){
        if(arr[i]+arr[j]==target){
            console.log(arr[i],arr[j])
        }
    }
}
複製代碼

使用map

var arr = [1,2,5,2,9];
var target = 4;
// 使用map
var m = new Map();
var res = []; // 存放索引
for(let i=0; i<arr.length ;i++){
    if(m.has(target-arr[i])){
      // 第一次遇到就往裏面存,這裏若存在必定是以前存入的,不會與此次起衝突
        res.push(i,m.get(target-arr[i])); 
        break;
    }
    m.set(arr[i],i);
}
console.log(res);
複製代碼

判斷數組中的元素是否惟一

使用set ,而後比較轉爲set以後的大小和原來的大小

var a = [1,2,3,4]
var b = [1,2,1,3];

function judge(arr){
    let s = new Set(arr);
    if(s.size==arr.length){
        return true;
    }
    return false;
}
var flag1 = judge(a);
var flag2 = judge(b);

console.log(flag1); //true
console.log(flag2); //false
複製代碼

移動零

將數組中全部元素值爲0的元素移動到數組的末尾
1)必須在原數組上操做,不能拷貝額外的數組
2)儘可能減小操做次數

用一個新索引記錄不是0的數,並添加到原數組中,以後補全沒有添加進去的0

var arr = [1,0,0,2,0,3,4,5];
var index = 0; //數組新的索引
const num = 0;//比較的對象

for(let i=0;i<arr.length;i++){
    if(arr[i]!=num){
        // 不爲零就用新索引添加到原數組中
        arr[index] = arr[i];
        index += 1;
    }
}
for(let i=index;i<arr.length;i++){
    arr[i] = num;//補上以前沒有添加的0
}
console.log(arr); //[ 1, 2, 3, 4, 5, 0, 0, 0 ]
複製代碼

JavaScript中的坑點

這裏有一個問題須要特別注意,若是字符串鍵值可以被強制類型轉換爲十進制數字的話,它就會被看成數字索引來處理。

var a = [];
a["13"] = 1;
console.log(a.length); //14
console.log(a); //[ <13 empty items>, 1 ]
複製代碼
相關文章
相關標籤/搜索