第二十五節(jié): ES6 數(shù)組擴(kuò)展

1. 擴(kuò)展運(yùn)算符

擴(kuò)展運(yùn)算符(spread)是三個(gè)點(diǎn)(...)圣蝎。它好比 rest 參數(shù)的逆運(yùn)算馋评,將一個(gè)數(shù)組轉(zhuǎn)為用逗號(hào)分隔的參數(shù)序列硼瓣。

console.log(...[1, 2, 3])
// 1 2 3

console.log(1, ...[2, 3, 4], 5)
// 1 2 3 4 5
[...document.querySelectorAll('div')]
// [<div>, <div>, <div>]

該運(yùn)算符將一個(gè)數(shù)組,變?yōu)閰?shù)序列谈息。


1.1 擴(kuò)展運(yùn)算符后可以為表達(dá)式
const arr = [
  ...(x > 0 ? ['a'] : []),
  'b',
];

如果擴(kuò)展運(yùn)算符后面是一個(gè)空數(shù)組缘屹,則不產(chǎn)生任何效果凛剥。

[...[], 1]
// [1]


1.2 替代了apply方法
// ES5 的寫法
function f(x, y, z) {
  // ...
}
var args = [0, 1, 2];
f.apply(null, args);

// ES6的寫法
function f(x, y, z) {
  // ...
}
let args = [0, 1, 2];
f(...args);


1.3 可以快速取出數(shù)組中的最大值
//es5
Math.max.apply(null,[1,5,2,8]) // 8
//es6
Math.max(...[1,5,2,8])//8
//上面兩種方法等同于
Math.max(1,5,2,8)


1.4 復(fù)制數(shù)組
//es5
const a1 = [1, 2];
const a2 = a1.concat();

a2[0] = 2;
a1 // [1, 2]

擴(kuò)展運(yùn)算符提供了復(fù)制數(shù)組的簡(jiǎn)便寫法侠仇。

const a1 = [1, 2];
// 寫法一
const a2 = [...a1];
// 寫法二
const [...a2] = a1;


1.5 合并數(shù)組

擴(kuò)展運(yùn)算符提供了數(shù)組合并的新寫法。

// ES5
[1, 2].concat(more)
// ES6
[1, 2, ...more]

var arr1 = ['a', 'b'];
var arr2 = ['c'];
var arr3 = ['d', 'e'];

// ES5的合并數(shù)組
arr1.concat(arr2, arr3);
// [ 'a', 'b', 'c', 'd', 'e' ]

// ES6的合并數(shù)組
[...arr1, ...arr2, ...arr3]
// [ 'a', 'b', 'c', 'd', 'e' ]


1.6. 與解構(gòu)組合使用

擴(kuò)展運(yùn)算符可以與解構(gòu)賦值結(jié)合起來犁珠,用于生成數(shù)組逻炊。

// ES5
a = list[0], rest = list.slice(1)
// ES6
[a, ...rest] = list

下面是另外一些例子。

const [first, ...rest] = [1, 2, 3, 4, 5];
first // 1
rest  // [2, 3, 4, 5]

const [first, ...rest] = [];
first // undefined
rest  // []

const [first, ...rest] = ["foo"];
first  // "foo"
rest   // []
const [...butLast, last] = [1, 2, 3, 4, 5];
// 報(bào)錯(cuò)

const [first, ...middle, last] = [1, 2, 3, 4, 5];
// 報(bào)錯(cuò)


1.7. 類數(shù)組轉(zhuǎn)數(shù)組

擴(kuò)展運(yùn)算符還可以將字符串轉(zhuǎn)為真正的數(shù)組犁享。

[...'hello']
// [ "h", "e", "l", "l", "o" ]

let nodeList = document.querySelectorAll('div');
let array = [...nodeList];


2. 數(shù)組循環(huán)

2.1 . 常用循環(huán)
for(var i = 0; i < arr.length; i++){

}
while(){
      
 }


2.2. ES 5 新增的循環(huán)方法

新增的循環(huán)都是數(shù)組身上的方法

  1. arr.forEach()
  2. arr.map()
  3. arr.filter()
  4. arr.some()
  5. arr.every()
以上這些方法接收的參數(shù)一模一樣,接受兩個(gè)參數(shù)

第一個(gè): 就是循環(huán)的回調(diào)函數(shù)

第二個(gè): 你希望this指向誰,這個(gè)參數(shù)用的少


2.2.1 forEach用法

在看看forEach的用法

// arr.forEach()
// forEach其實(shí)就是for循環(huán),for里面循環(huán)變量的,自增啊,forEach就簡(jiǎn)單多了
var arr = ["a","b","c","d"]
arr.forEach(function(value,index,arr){
    console.log(value,index,arr);
})
// forEach 就是用來代替我們for循環(huán)的

forEach的this

var arr = ["a","b","c","d"]
arr.forEach(function(value,index,arr){
    console.log(this); // 此時(shí)this是window
    console.log(value,index,arr);
})

// 如果傳了第二個(gè)參數(shù)
var arr = ["a","b","c","d"]
arr.forEach(function(value,index,arr){
    console.log(this); // 此時(shí)this就是#document
    console.log(value,index,arr);
},document)

如果使用箭頭函數(shù),那么this就會(huì)發(fā)生變化

var arr = ["a","b","c","d"]
arr.forEach((value,index,arr) => {
    console.log(this); // 此時(shí)this就是window
    console.log(value,index,arr);
})

// 添加第二個(gè)參數(shù)
var arr = ["a","b","c","d"]
arr.forEach((value,index,arr) => {
    console.log(this); // 此時(shí)this還是window
    console.log(value,index,arr);
},document)
// 箭頭函數(shù)里面的this指向函數(shù)定義時(shí)的this

// 將代碼放到一個(gè)對(duì)象中
var obj= {
    name: function(){
        var arr = ["a","b","c","d"]
        arr.forEach((value,index,arr) => {
            console.log(this); // 此時(shí)this還是obj
            console.log(value,index,arr);
        },document)
    }
}
// 此時(shí)obj.name()  this指向obj


2.2.2 map

翻譯過來就是地圖(映射),非常有用,尤其是數(shù)據(jù)交互

正常情況下,需要配合return使用,返回新數(shù)組,如果沒有return,這個(gè)就相當(dāng)于forEach

forEach 返回undefined

map如果沒有return 則返回元素項(xiàng)數(shù)個(gè)undefined組成的新數(shù)組

// arr.map()
let arr= [
    {title: "aa",read: 100},
    {title: "aa",read: 100},
    {title: "aa",read: 100}
]
let newArr = arr.map((item,index,arr) => {
    console.log(item,index,arr);
    return item;
})

注意

平時(shí)只用用map,就一定要有return,否則你就用forEach 不要走我map了

map 可以重新整理我們的數(shù)據(jù)結(jié)構(gòu)

// arr.map()  整理后臺(tái)傳過來的數(shù)據(jù)
let arr= [
    {title: "aa",read: 100},
    {title: "bb",read: 20},
    {title: "cc",read: 50}
]
let newArr = arr.map((item,index,arr) => {
    let json = {};
    json.shop = `*${item.title}--`;
    json.price = `¥${item.read}元`
    return json;
})
console.log(arr);
console.log(newArr);


2.2.3 filte

過濾,過濾一些不合格的元素,如果回調(diào)函數(shù)返回true,就留下來,添加到返回的新數(shù)組中,為false就過濾

// arr.filter()  過濾
let arr= [
    {title: "aa",read: 100},
    {title: "bb",read: 20},
    {title: "cc",read: 50}
]
let newArr = arr.filter((item,index,arr) => {
    return item.read > 50;
})
console.log(arr);
console.log(newArr);

filte方法去重

let arr = [2,1,3,5,2,3,1];
let newArr = arr.filter((val,index,arr)=>{
    return arr.indexOf(val) == index;
})
console.log(newArr);   // [2, 1, 3, 5]


2.2.4 some every

這個(gè)方法感覺像查找比對(duì)的意思,返回的結(jié)果是布爾值

let arr = ["a","b","c","d"]
let b = arr.some((item,index,arr) => {
    return item == "c";
})
console.log(b);  // true

只要在回調(diào)中返回一個(gè)true 那么整個(gè)結(jié)果就是true,

感覺像查詢,數(shù)組中只要有一項(xiàng)符合條件,那么就返回true,如果都是false 那結(jié)果就是false

// every  判斷數(shù)組里面是不是都是奇數(shù)
let arr = [1,3,7,9,5]
let b = arr.every((item,index,arr) => {
    return item % 2 == 1;
})
console.log(b);   // true

而every則剛好相反,every是數(shù)組中每一項(xiàng)都為true,才返回true ,只要有一項(xiàng)不符合條件都是false

來封裝一個(gè)小功能

let arr = ["apple","banana","orange"]

function finedInArray(arr,item){
    return arr.some((val,index,arr) => {
        return val == item;
    })
}

console.log(finedInArray(arr,"orange"));  // true



接下來reduce和reduceRight接收的參數(shù)和上面方法都不一樣了

2.2.5 reduce reduceRight

reduce

從左往右計(jì)算

reduceRight

是從右往左計(jì)算

用的極少,比如求數(shù)組的和,階乘都可以

let arr = [1,2,3,4,5,6,7,8,9,10]
let res = arr.reduce((prev,cur,index,arr) => {
    // console.log(arguments);
    return prev + cur;
})
console.log(res);  //55

prev是上一次的運(yùn)算結(jié)果,cur是當(dāng)前的值,index是當(dāng)前的下標(biāo),arr是當(dāng)前的數(shù)組

數(shù)組去重

let arr = [1,2,2,4,5,4,7,5,6,1]
let res = arr.reduce(function(prev,cur,index,arr){
    //console.log(arguments);
    if(!prev.includes(cur)){
        prev.push(cur)
    }
    return prev;
},[])
console.log(res);


3.ES 6 新增的循環(huán)

es6引入的作為遍歷所有數(shù)據(jù)結(jié)構(gòu)的統(tǒng)一的方法余素。

一個(gè)數(shù)據(jù)結(jié)構(gòu)只要部署了Symbol.iterator屬性,就被視為具有 iterator 接口炊昆,就可以用for...of循環(huán)遍歷它的成員桨吊。也就是說,for...of循環(huán)內(nèi)部調(diào)用的是數(shù)據(jù)結(jié)構(gòu)的Symbol.iterator方法凤巨。

3.1. for ... of 循環(huán)

arr.keys() 數(shù)組下標(biāo)集合

arr.values() 數(shù)組值集合

arr.entries() 數(shù)組的每一項(xiàng)的集合

entries()视乐,keys()values()——用于遍歷數(shù)組。它們都返回一個(gè)遍歷器對(duì)象敢茁,可以用for...of循環(huán)進(jìn)行遍歷佑淀,唯一的區(qū)別是keys()是對(duì)鍵名的遍歷、values()是對(duì)鍵值的遍歷彰檬,entries()是對(duì)鍵值對(duì)的遍歷伸刃。

let arr = ["apple","banana","orange"];
for(let val of arr){
    console.log(val);
}

// 和for循環(huán)很像
// 這個(gè)只是循環(huán)值,如果循環(huán)索引怎么辦
for(let index of arr.keys()){
    console.log(index);
}
// arr.keys() 就是arr數(shù)組索引的集合

// 如果想索引和值一起循環(huán)
for(let item of arr.entries()){
    console.log(item);   // item 是有數(shù)組的下標(biāo)和值組成的數(shù)組如[0,"apple"]
}

// 也可以像下面這樣寫
for(let [key, val] of arr.entries()){
    console.log(key, val);   // 打印索引和值 0 "apple"
}


4.ES6 數(shù)組新增方法

4.1. Array.from()

作用: 把類數(shù)組(獲取一組元素,arguments)對(duì)象轉(zhuǎn)成數(shù)組

4.1.1 拷貝數(shù)組
// ES5的方法
var arr2 = [].slice.call(arr);
var arr2 = Array.prototype.slice.call(arr);

// ES6的方法
let arr = [1,2,3];
let arr2 = [...arr];

// 第二種就是 
let arr3 = Array.from(arr);


4.1.2 Array.from()

參數(shù):

  • 第一個(gè)參數(shù):一個(gè)類數(shù)組對(duì)象,用于轉(zhuǎn)為真正的數(shù)組
  • 第二個(gè)參數(shù):類似于數(shù)組的map方法逢倍,用來對(duì)每個(gè)元素進(jìn)行處理捧颅,將處理后的值放入返回的數(shù)組。
  • 第三個(gè)參數(shù):如果map函數(shù)里面用到了this關(guān)鍵字较雕,還可以傳入Array.from的第三個(gè)參數(shù)碉哑,用來綁定this
// 將arguments轉(zhuǎn)數(shù)組
function haha(){
    console.log(arguments);  // 類數(shù)組
    console.log(Array.from(arguments)); // 數(shù)組
}
haha(1,2,3,4)

什么是類數(shù)組.有l(wèi)ength就靠譜

var str = "wuwei";
var arr = Array.from(str);
console.log(arr); // 此時(shí)arr就是一個(gè)數(shù)組了
var obj = {
    0: "a",
    1: "b",
    2: "c",
    length: 3
}
var arr = Array.from(obj);   // ["a", "b", "c"]


4.2. Array.of()

把一組值轉(zhuǎn)成數(shù)組

 var arr = Array.of("a","b","c","d");

這個(gè)方法的主要目的郎笆,是彌補(bǔ)數(shù)組構(gòu)造函數(shù)Array()的不足谭梗。因?yàn)閰?shù)個(gè)數(shù)的不同,會(huì)導(dǎo)致Array()的行為有差異宛蚓。

//Array
Array() // []
Array(3) // [, , ,]
Array(3, 11, 8) // [3, 11, 8]

Array.of(3, 11, 8) // [3,11,8]
Array.of(3) // [3]
Array.of(3).length // 1



4.3. arr.find()

查找第一個(gè)符合要求的數(shù)組成員,返回值,如果沒找到,則返回undefined

var arr = [50,10,201,103,62,81];
var res = arr.find((val , index ,arr) => {
    // console.log(arguments)
    return val > 100;
})
console.log(res);   // 201


4.4. arr.findIndex()

和find()很像,這是這里找的是位置,返回條件為真時(shí)的索引;沒找到返回-1

var arr = [50,10,201,103,62,81];
var res = arr.findIndex((val , index ,arr) => {
    return val > 100;
})
console.log(res);   // 2


4.5.arr.fill()

arr.fill(需要填充的值, 填充開始位置,填充結(jié)束位置);

填充內(nèi)容不包括結(jié)束的位置

var arr = new Array(3);
arr.fill("默認(rèn)值");
console.log(arr);  //["默認(rèn)值", "默認(rèn)值", "默認(rèn)值"]

// 完整用法
var arr = new Array(10);
arr.fill("默認(rèn)值",1,3);
console.log(arr);  // [empty, "默認(rèn)值", "默認(rèn)值", empty × 7]


5. ES2016里面新增

5.1. arr.includes()

查看數(shù)組中是否包含參數(shù)的值,返回布爾值

var arr = ["apple" , "origan","banana"];
var a = arr.includes("apple");
console.log(a);   // true

var b = arr.includes("apple2");
console.log(b);   // false

以前我們判斷是使用indexOf 判斷,結(jié)果為-1就是不包含

沒有該方法之前激捏,我們通常使用數(shù)組的indexOf方法,檢查是否包含某個(gè)值凄吏。

indexOf方法有兩個(gè)缺點(diǎn)远舅,一是不夠語義化闰蛔,它的含義是找到參數(shù)值的第一個(gè)出現(xiàn)位置,所以要去比較是否不等于-1图柏,表達(dá)起來不夠直觀序六。二是,它內(nèi)部使用嚴(yán)格相等運(yùn)算符(===)進(jìn)行判斷蚤吹,這會(huì)導(dǎo)致對(duì)NaN的誤判例诀。


6.關(guān)于數(shù)組的空位

數(shù)組的空位指,數(shù)組的某一個(gè)位置沒有任何值裁着。

注意繁涂,空位不是undefined,一個(gè)位置的值等于undefined二驰,依然是有值的扔罪。空位是沒有任何值桶雀,in運(yùn)算符可以說明這一點(diǎn)矿酵。

0 in [undefined, undefined, undefined] // true
0 in [, , ,] // false

ES5 對(duì)空位的處理,已經(jīng)很不一致了矗积,大多數(shù)情況下會(huì)忽略空位全肮。

  • forEach(), filter(), reduce(), every()some()都會(huì)跳過空位。
  • map()會(huì)跳過空位漠魏,但會(huì)保留這個(gè)值
  • join()toString()會(huì)將空位視為undefined倔矾,而undefinednull會(huì)被處理成空字符串。

ES6 則是明確將空位轉(zhuǎn)為undefined柱锹。

Array.from方法會(huì)將數(shù)組的空位哪自,轉(zhuǎn)為undefined,也就是說禁熏,這個(gè)方法不會(huì)忽略空位壤巷。

Array.from(['a',,'b'])
// [ "a", undefined, "b" ]

擴(kuò)展運(yùn)算符(...)也會(huì)將空位轉(zhuǎn)為undefined

[...['a',,'b']]
// [ "a", undefined, "b" ]

fill()會(huì)將空位視為正常的數(shù)組位置瞧毙。

new Array(3).fill('a') // ["a","a","a"]

for...of循環(huán)也會(huì)遍歷空位胧华。

let arr = [, ,];
for (let i of arr) {
  console.log(1);
}
// 1
// 1

上面代碼中,數(shù)組arr有兩個(gè)空位宙彪,for...of并沒有忽略它們矩动。如果改成map方法遍歷,空位是會(huì)跳過的释漆。

entries()悲没、keys()values()男图、find()findIndex()會(huì)將空位處理成undefined示姿。

// entries()
[...[,'a'].entries()] // [[0,undefined], [1,"a"]]

// keys()
[...[,'a'].keys()] // [0,1]

// values()
[...[,'a'].values()] // [undefined,"a"]

// find()
[,'a'].find(x => true) // undefined

// findIndex()
[,'a'].findIndex(x => true) // 0

由于空位的處理規(guī)則非常不統(tǒng)一甜橱,所以建議避免出現(xiàn)空位。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末栈戳,一起剝皮案震驚了整個(gè)濱河市诞挨,隨后出現(xiàn)的幾起案子棉磨,更是在濱河造成了極大的恐慌瘟裸,老刑警劉巖陶衅,帶你破解...
    沈念sama閱讀 222,378評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異命锄,居然都是意外死亡堰乔,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,970評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門脐恩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人侦讨,你說我怎么就攤上這事驶冒。” “怎么了韵卤?”我有些...
    開封第一講書人閱讀 168,983評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵骗污,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我沈条,道長(zhǎng)需忿,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,938評(píng)論 1 299
  • 正文 為了忘掉前任蜡歹,我火速辦了婚禮屋厘,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘月而。我一直安慰自己汗洒,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,955評(píng)論 6 398
  • 文/花漫 我一把揭開白布父款。 她就那樣靜靜地躺著溢谤,像睡著了一般。 火紅的嫁衣襯著肌膚如雪憨攒。 梳的紋絲不亂的頭發(fā)上世杀,一...
    開封第一講書人閱讀 52,549評(píng)論 1 312
  • 那天,我揣著相機(jī)與錄音肝集,去河邊找鬼瞻坝。 笑死,一個(gè)胖子當(dāng)著我的面吹牛包晰,可吹牛的內(nèi)容都是我干的湿镀。 我是一名探鬼主播炕吸,決...
    沈念sama閱讀 41,063評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼勉痴!你這毒婦竟也來了赫模?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,991評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤蒸矛,失蹤者是張志新(化名)和其女友劉穎瀑罗,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體雏掠,經(jīng)...
    沈念sama閱讀 46,522評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡斩祭,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,604評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了乡话。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片摧玫。...
    茶點(diǎn)故事閱讀 40,742評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖绑青,靈堂內(nèi)的尸體忽然破棺而出诬像,到底是詐尸還是另有隱情,我是刑警寧澤闸婴,帶...
    沈念sama閱讀 36,413評(píng)論 5 351
  • 正文 年R本政府宣布坏挠,位于F島的核電站,受9級(jí)特大地震影響邪乍,放射性物質(zhì)發(fā)生泄漏降狠。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,094評(píng)論 3 335
  • 文/蒙蒙 一庇楞、第九天 我趴在偏房一處隱蔽的房頂上張望榜配。 院中可真熱鬧,春花似錦姐刁、人聲如沸芥牌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,572評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽壁拉。三九已至,卻和暖如春柏靶,著一層夾襖步出監(jiān)牢的瞬間弃理,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,671評(píng)論 1 274
  • 我被黑心中介騙來泰國(guó)打工屎蜓, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留痘昌,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,159評(píng)論 3 378
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像辆苔,于是被迫代替她去往敵國(guó)和親算灸。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,747評(píng)論 2 361