一庇谆、數(shù)組的增刪改查
增加數(shù)組元素的方法有push / unshift赁遗,刪除數(shù)組元素的方法有pop / shift,還有萬能的增刪改都可以的splice族铆,以及查找數(shù)組元素的indexOf / lastIndexOf,下面我們一一講解下區(qū)別哭尝。
1. push方法
從數(shù)組的最后插入(push壓入)新元素哥攘,返回的結(jié)果是數(shù)組的長度。
var arr = [0, 1, 2, 3];
arr.push(4); // arr變成[0, 1, 2, 3, 4],此句執(zhí)行的結(jié)果是arr.length即5
arr.push(5, 6); // arr變成[0, 1, 2, 3, 4, 5, 6]逝淹,此句執(zhí)行的結(jié)果是arr.length即7
2. pop方法
與push相對應(yīng)的耕姊,pop是將數(shù)組的最后一個元素刪除(pop彈出),返回的結(jié)果是被刪除的該元素栅葡。
var arr = [1, 2, 3, 4];
arr.pop(); // arr變成[1, 2, 3]茉兰,此句執(zhí)行的結(jié)果是被刪除的元素4
3. unshift方法
unshift也是插入新元素,不過是從數(shù)組的最開始插入欣簇,返回的結(jié)果也是插入后數(shù)組的長度规脸。
var arr = [0, 1, 2, 3];
arr.unshift(4); // arr變成[4, 0, 1, 2, 3],此句執(zhí)行的結(jié)果是arr.length即5
arr.unshift(5, 6); // arr變成[5, 6, 4, 0, 1, 2, 3]熊咽,此句執(zhí)行的結(jié)果是arr.length即7
4. shift方法
與unshift對應(yīng)的莫鸭,shift是刪除最開始即第一個元素,返回的結(jié)果是被刪除的該元素横殴。
var arr = [1, 2, 3, 4];
arr.shift(); // arr變成[2, 3, 4]被因,此句執(zhí)行的結(jié)果是被刪除的元素1
5. splice方法
splice方法就比較強(qiáng)大了,可以增加刪除和查看元素衫仑,而且還可以指定位置梨与。使用方法splice(index, num, value1, value2, ..., valuen),第一個參數(shù)是操作的位置文狱,第二個參數(shù)是改變的元素個數(shù)粥鞋,第三個是插入或替換的值,后面也都是要插入和替換的值如贷。返回的結(jié)果是被改變元素構(gòu)成的數(shù)組陷虎。
var arr = [1, 2, 3, 4];
// 增加元素,由于增加元素不會改變原數(shù)組元素的值杠袱,所以第二個參數(shù)為0
arr.splice(1, 0, 5); // 在數(shù)組下標(biāo)為1即數(shù)組里元素2的位置尚猿,插入一個元素5,數(shù)組變?yōu)閇1, 5, 2, 3, 4]楣富,此句返回結(jié)果是[](因?yàn)樵瓟?shù)組沒有被刪除或替換的元素)凿掂。
arr.splice(0, 0, 6, 7); // 數(shù)組變?yōu)閇6, 7, 1, 5, 2, 3, 4],返回的也是[]
// 刪除元素纹蝴,由于刪除不需要新插入和替換的值庄萎,所以只需傳前兩個參數(shù)
arr.splice(0, 3); // 從index為0的位置開始,從左往右刪除3個元素塘安,數(shù)組變?yōu)閇5, 2, 3, 4]糠涛,此句返回的結(jié)果是[6, 7, 1]
arr.splice(3, 8); // 從index為3的位置開始,數(shù)組變?yōu)閇5, 2, 3]兼犯,此句返回[4]
// 替換元素忍捡,替換元素由于原數(shù)組的元素有變化集漾,所以不為0,注意替換的個數(shù)和后面?zhèn)鞯脑貍€數(shù)不一致可以做到替換的同時增刪
arr.splice(0, 3, 1, 2, 3); // 從第一個元素開始砸脊,從左往右替換3個元素具篇,數(shù)組變?yōu)閇1, 2, 3],輸出結(jié)果為被替換元素數(shù)組[5, 2, 3]
arr.splice(0, 2, 3, 2, 1, 2); // 替換的同時添加凌埂,此時arr為[3, 2, 1, 2, 3]驱显,返回結(jié)果[5, 2]
arr.splice(2, 3, 1, 0); // 替換的同時刪除,此時arr為[3, 2, 1, 0]瞳抓,返回結(jié)果為[1, 2, 3]
或許有小伙伴已經(jīng)被繞暈了埃疫,其實(shí)沒必要記住那么多規(guī)律,知道每個參數(shù)代表啥再去推算就好挨下,多看看例子就明白了熔恢。
6. indexOf和lastIndexOf方法
第一個參數(shù)指定查找元素,第二個參數(shù)指定從哪個位置開始找(沒設(shè)默認(rèn)0開始找)臭笆,返回第一次被找到的下標(biāo)值叙淌,若沒有返回-1。而lastIndexOf基本類似愁铺,只是從最后一個元素開始倒著找鹰霍。若第二個參數(shù)超出數(shù)組的長度范圍,則直接返回-1茵乱。
var arr = ['str', 1, 2, 'str', 6];
arr.indexOf('str'); // 0
arr.indexOf('str', 1); // 4茂洒,從第二位開始往后找
arr.lastIndexOf('str'); // 4
arr.lastIndexOf('str', 1); // 0,從倒數(shù)第二位開始往前找
arr.indexOf('haha'); // -1
arr.indexOf('str', -1); // -1
arr.indexOf('str', 5); // -1
注意瓶竭,其內(nèi)部用的是嚴(yán)格等于(===)去比較是否相等督勺,所以無法查找NaN,因?yàn)镹aN===NaN返回false斤贰。
var arr = ['1', 1, 2, NaN];
arr.indexOf(1); // 1
arr.indexOf('1'); // 0
arr.indexOf(NaN); // -1
arr.lastIndexOf(NaN); // -1
二智哀、數(shù)組的排序
1. sort方法
sort用于數(shù)組排序,會改變原數(shù)組荧恍,返回值是排好序的數(shù)組瓷叫。有兩種調(diào)用方式:
- 直接調(diào)用,則按默認(rèn)排序送巡。即按數(shù)字大小或字符串的unicode編碼大小進(jìn)行排序摹菠,對象會調(diào)用toString()再按編碼排序,若有undefined則放在最后骗爆。
- 傳自定義函數(shù)作為參數(shù)調(diào)用次氨,當(dāng)這個函數(shù)返回負(fù)值時表示第一個數(shù)應(yīng)該位于第二個數(shù)前面,當(dāng)返回0則相等摘投,當(dāng)返回正值時表示第一個數(shù)應(yīng)該位于第二個數(shù)后面煮寡。
var arr1 = [1, 5, 2, 8, 6];
arr1.sort(); // [1, 2, 5, 6, 8]
var arr2 = ['1', '8', '7', '10'];
arr2.sort(); // ["1", "10", "7", "8"]屉佳,字符串先比較的第一位的unicode編碼值
// 為了得到正確的排序數(shù)組可以自定義函數(shù)
arr2.sort(function(a, b) {
return a - b; // 由于減法運(yùn)算會先轉(zhuǎn)數(shù)字再運(yùn)算,所以可以正確排序
}); // ["1", "7", "8", "10"]
一般數(shù)字的對比洲押,直接用減法就滿足需求;如果是字符串要比較unicode值大小的圆凰,可以用><進(jìn)行判斷杈帐。看下面兩個比較常見的例子:
// 要求按姓名進(jìn)行排序
var users = [
{name: 'Peter', born: '2018-7-12'},
{name: 'Bake', born: '2018-3-15'},
{name: 'John', born: '2016-4-18'}
];
users.sort(function(a, b) {
if(a.name > b.name) {return 1;}
else if(a.name < b.name) {return -1;}
else {return 0;}
});
// [{name:"Bake", born:"2018-3-15"}, {name:"John", born:"2016-4-18"}, {name:"Peter", born:"2018-7-12"}]
// 要求按出生日期先后進(jìn)行排序
users.sort(function(a, b) {
return new Date(a.born) - new Date(b.born);
});
// [{name:"John", born:"2016-4-18"}, {name:"Bake", born:"2018-3-15"}, {name:"Peter", born:"2018-7-12"}]
2. reverse方法
將數(shù)組進(jìn)行逆序专钉,會改變原數(shù)組挑童,返回值會逆序數(shù)組。注意是逆序(反轉(zhuǎn)下前后順序)跃须,而不是倒序(按順序遞減排好)站叼。
var arr = [1, 5, 3, 8, 6];
arr.reverse(); // [6, 8, 3, 5, 1]
三、數(shù)組的拼接
1. join方法
用指定參數(shù)作為分隔符連接數(shù)組元素菇民,返回連接后的字符串尽楔。若沒參數(shù)默認(rèn)是','連接,若是有空位或undefined或null則轉(zhuǎn)成空字符連接第练。
var arr = [1, 5, , 8, undefined, 6, null, 7];
arr.join('-'); // "1-5--8--6--7"
arr.join(); // "1,5,,8,,6,,7"
2. concat方法
concat用于數(shù)組或數(shù)組元素的合并阔馋,返回一個合并后的新數(shù)組,注意原數(shù)組不發(fā)生改變娇掏。
var arr1 = [1, 2], arr2 = [3, 4];
arr1.concat(arr2); // [1, 2, 3, 4]
arr1.concat({a: 1, b: 2}, {c: 3}); // [1, 2, {a:1, b:2}, {c:3}]
arr1.concat(3, 4, 5); // [1, 2, 3, 4, 5]
注意呕寝,若合并的元素是對象,則concat合并后的元素是引用婴梧,所以可以用來淺拷貝對象下梢。
var arr = [1, 2, {a: 3, b: 4}];
var newArr = [].concat(arr); // 或者arr.concat(),都返回[1, 2, {a:3, b:4}]
newArr[2].a = 666;
console.log(arr); // [1, 2, {a:666, b:4}]塞蹭,由于是引用孽江,所以原來arr的a也會被改變
四、數(shù)組元素處理
1. reduce方法
reduce方法接受兩個參數(shù)浮还,第一個參數(shù)是一個函數(shù)竟坛,第二個參數(shù)是默認(rèn)初始值。而第一個函數(shù)也有兩個參數(shù)钧舌,第一個參數(shù)是數(shù)組第一個元素或初始值或上一個函數(shù)返回的結(jié)果担汤,第二個參數(shù)是數(shù)組的下個元素凉当。來看個例子:
var arr = [1, 2, 3];
arr.reduce(function(a, b) {
return a + b;
});
// 第一次:沒有初始值洞渔,a是數(shù)組第一個元素1番甩,b是下個元素2
// 第二次:a是上次函數(shù)的結(jié)果3忽冻,b是下個元素3
// 沒有下個數(shù)組元素娄帖,遍歷結(jié)束摆马,結(jié)果返回6
arr.reduce(function(a, b) {
return a + b;
}, 4);
// 第一次:有初始值矩动,a是初始值4撑刺,b此時是第一個元素1
// 第二次:a是上次函數(shù)的結(jié)果5,b是下個元素2
// 第三次:a是上次函數(shù)的結(jié)果7所宰,b是下個元素3
// 沒有下個數(shù)組元素绒尊,遍歷結(jié)束,結(jié)果返回10
一般盡量指定一個默認(rèn)初始值仔粥,因?yàn)闆]有初始值對空數(shù)組reduce處理會報錯婴谱。
[].reduce(function(a, b) {
return a + b;
}); // Uncaught TypeError: Reduce of empty array with no initial value
[].reduce(function(a, b) {
return a + b;
}, 0); // 0
reduce主要用處是存儲上個元素遍歷的處理結(jié)果,用于下個元素處理躯泰,來看看兩個例子:
(1)找最大長度字符串
['hello js', 'hello', 'js'].reduce(function(longest, value) {
return value.length > longest.length ? value : longest;
}, '');
// "hello js"
(2)數(shù)組元素去重
// 合并兩個數(shù)組谭羔,當(dāng)cardUrl一樣時保留arr1的元素
var arr1 = [
{url:'/a',cardUrl:'rUbAF3EFJjyyfYRrU3zIj2Ez'},
{url:'/b',cardUrl:'JnAfYbvqaQfy6bqyeiEjIZjm'},
{url:'/c',cardUrl:'7r2MFfzyQVryeEVVf2QfU7nq'},
],
arr2 = [
{url:"/d",cardUrl:"nua67bfa6n2qr2eUJbimeaQj"},
{url:'/e',cardUrl:"rUbAF3EFJjyyfYRrU3zIj2Ez"},
];
let arr = [...arr1,...arr2]; // 拼接數(shù)組,相當(dāng)于concat
let hash = {};
arr = arr.reduce(function(item, next) { // 如果已存在則丟棄麦向,否則放入結(jié)果集
hash[next.cardUrl] ? '' : hash[next.cardUrl] = true && item.push(next);
return item;
}, []);
/* [
{url: "/a", cardUrl: "rUbAF3EFJjyyfYRrU3zIj2Ez"},
{url: "/b", cardUrl: "JnAfYbvqaQfy6bqyeiEjIZjm"},
{url: "/c", cardUrl: "7r2MFfzyQVryeEVVf2QfU7nq"},
{url: "/d", cardUrl: "nua67bfa6n2qr2eUJbimeaQj"}
] */
2. reduceRight方法
此法與reduce用法基本一致瘟裸,只是遍歷的時候是倒序遍歷。
var arr = [1, 2, 3];
arr.reduceRight(function(a, b) {
return a + b;
}, 4);
// 第一次:有初始值诵竭,a是初始值4话告,b此時是倒數(shù)第一個元素3
// 第二次:a是上次函數(shù)的結(jié)果7,b是倒數(shù)第二個元素2
// 第三次:a是上次函數(shù)的結(jié)果9秀撇,b是倒數(shù)第三個元素1
// 沒有倒數(shù)第四個數(shù)組元素超棺,遍歷結(jié)束,結(jié)果返回10