前言
在面試的時(shí)候,ES6幾乎已成必問(wèn)問(wèn)題,對(duì)ES6還摸棱兩可的小伙伴們看完這篇文章將不再迷茫,建議收藏。
1.let 變量聲明以及特性
聲明變量
let a;
let b, c, d;
let e = 1;
let f = 2, g = 3;
特性
- 不能重復(fù)聲明
- 塊級(jí)作用域 只在塊級(jí)作用域有效
- 沒(méi)有變量提升
- 不影響作用域鏈
2.const 常量聲明以及特性
特性
- 必須有初始值
- 一般常量使用大寫(xiě)
- 常量的值不能修改
- 也是塊級(jí)作用域
- 對(duì)于數(shù)組和對(duì)象的修改,不算對(duì)常量的修改,不會(huì)報(bào)錯(cuò)(可以對(duì)數(shù)組和對(duì)象進(jìn)行修改,指向的地址沒(méi)有改變)
3.變量的解構(gòu)賦值
數(shù)組的解構(gòu)
const RNG = ['uzi', 'mlxg', 'letme', 'ming']
let [a, b, c, d] = RNG;// 每個(gè)值就是數(shù)組的位置對(duì)應(yīng)的值
對(duì)象的解構(gòu)
const UZI= {
name: '自豪',
age: 22,
love: 'LOL',
lol: function(){
alert('打lol')
}
}
let {name, age, love} = UZI;// 每個(gè)值是對(duì)象中對(duì)應(yīng)的值
let {lol} = UZI;
lol();// 使用
4.模板字符串 ``
內(nèi)容中可以直接出現(xiàn)換行符,單引號(hào)雙引號(hào)內(nèi)容不能直接用換行符(需要通過(guò)引號(hào)加號(hào)拼接)
let str = `lol s10
tes 是冠軍`;// 可以這樣直接使用換行符
直接進(jìn)行變量的拼接 ${}
let lol = 'lol十周年';
let uzi = `${lol} 中國(guó)隊(duì)奪冠`
5.對(duì)象的簡(jiǎn)寫(xiě)
let name = 'zhangning187';
let change = function(){
console.log('努力改變');
}
const supwisdom = {
name,
change
}
6.箭頭函數(shù)及聲明特點(diǎn) =>
let fn = (a, b) => {
return a + b;
}
fn(1, 2);// 3
特點(diǎn)
- 1.this是靜態(tài)的,this始終是指向函數(shù)聲明時(shí)所在作用域下的this值,他沒(méi)有自己的this
- 2.不能作為構(gòu)造實(shí)例化對(duì)象
- 3.不能使用arguments變量
- 4.箭頭函數(shù)的簡(jiǎn)寫(xiě)
省略小括號(hào),當(dāng)形參有且只有一個(gè)的時(shí)候可以省略
let add = n => {
return n*2;
}
省略花括號(hào),當(dāng)代碼體只有一條語(yǔ)句的時(shí)候,return 必須省略,語(yǔ)句的執(zhí)行結(jié)果就是函數(shù)的返回值
let add = n => n*2;
7.函數(shù)參數(shù)的默認(rèn)值
形參初始值
function add(a, b, c = 10) {// 當(dāng)不傳遞c的時(shí)候,c的默認(rèn)值是10,盡量把具有默認(rèn)值的參數(shù)放在后面
return a + b + c;
}
add (1, 2);// 13
與解構(gòu)賦值結(jié)合
function con({name, age, love, height = '18'}) {// 還可以給默認(rèn)值
console.log(age);// 24
console.log(height);// 沒(méi)有傳遞,使用默認(rèn)值 18
}
con({
name: 'zhangning187',
age: 24,
love: 'js'
})
8.rest參數(shù)
用于獲取參數(shù)的實(shí)參,用于代替arguments
rest參數(shù)是一個(gè)數(shù)組和es5中的arguments不一樣,arguments里面是一個(gè)對(duì)象
獲取實(shí)參的方式
function data(a, b, ...args) {// rest 參數(shù)必須放到參數(shù)的最后面
console.log(a);// 1
console.log(b);// 2
console.log(args);// [3, 4, 5, 6, 7]
}
data(1, 2, 3, 4, 5, 6, 7);
9.擴(kuò)展運(yùn)算符 ...
可以將數(shù)組轉(zhuǎn)換為逗號(hào)分隔的參數(shù)序列,將一個(gè)數(shù)組分割,并將各個(gè)項(xiàng)作為分離的參數(shù)序列傳遞給函數(shù)
const RNG = ['UZI', 'MLXG', 'LETME', 'MING'];
console.log(...RNG)// UZI MLXG LETME MING 解構(gòu)之后的序列
console.log(RNG);// ['UZI', 'MLXG', 'LETME', 'MING'] 返回的是一個(gè)數(shù)組
const a = [1,2], b=[3,6];
const c = [...a, ...b];// [1, 2, 3, 6]
10.Symbol 新的原始數(shù)據(jù)類(lèi)型,表示獨(dú)一無(wú)二的值
他是javaScript 語(yǔ)言的第七種數(shù)據(jù)類(lèi)型,是一種類(lèi)似于字符串的數(shù)據(jù)類(lèi)型
特點(diǎn)
- 1.Symbol 的值是唯一的,用來(lái)解決命名沖突的問(wèn)題
- 2.Symbol 值不能與其他數(shù)據(jù)進(jìn)行運(yùn)算,也不能自己運(yùn)算 + - * /
- 3.Symbol 定義的對(duì)象屬性不能使用for in循環(huán)遍歷,但是可以使用 Reflect.ownKeys 來(lái)獲取對(duì)象的所有鍵名
//創(chuàng)建Symbol
let s = Symbol();// s不可見(jiàn),在內(nèi)部實(shí)現(xiàn)唯一性
let s2 = Symbol('zhangning187');// 這里面的字符串只是一個(gè)標(biāo)志,Symbol返回的值都是唯一的
let s3 = Symbol('zhangning187');
console.log(s2 == s3);// false,確定唯一性
//Symbol.for()方法創(chuàng)建,這是一個(gè)對(duì)象,這種方式可以得出唯一的Symbol值
let s6 = Symbol.for('zhangning187');
let s8 = Symbol.for('zhangning187');
console.log(s6 ==s8);// true 得到唯一的Symbol值
對(duì)象添加Symbol類(lèi)型的屬性
let zn = {
up: function(){},
down: function(){},
name: 'zhangning187',
age: 24
}
// 向?qū)ο髗n中添加 up down 方法
// zn.up = function(){}// 這個(gè)可以添加但是不確定zn中是否存在up方法,可能會(huì)覆蓋原來(lái)的up方法
// 這時(shí)候需要考慮通過(guò)Symbol添加唯一的方法
// 聲明一個(gè)對(duì)象
let methods = {
up: Symbol(),
down: Symbol()
}
zn[methods.up] = function(){
console.log('我可以爬樓');
}
zn[methods.down] = function(){
console.log('我可以下樓');
}
console.log(zn);// 已經(jīng)添加唯一的方法 up down
let UZI = {
name: '自豪',
// Symbol(): function(){},// 這里不能這樣直接使用, Symbol()是一個(gè)表達(dá)式,是一個(gè)動(dòng)態(tài)的
[Symbol('lol')]: function(){
console.log('我會(huì)打lol');
},
[Symbol('籃球')]: function(){// Symbol()中還可以添加描述字符串
console.log('我可以打籃球')
}
}
console.log(UZI);
11.迭代器(Iterator)
迭代器是一種接口,為各種不同的數(shù)據(jù)結(jié)構(gòu)提供統(tǒng)一的訪(fǎng)問(wèn)機(jī)制,任何數(shù)據(jù)結(jié)構(gòu)只要部署Iterator接口,就可以完成遍歷操作
1.ES6創(chuàng)造了一種新的遍歷命令for...of循環(huán),Iterator接口提供for...of消費(fèi)
2.原生具備iterator接口的數(shù)據(jù)
Array Arguments Set Map String TypedArray NodeList
3.工作原理
- a 創(chuàng)建一個(gè)指針對(duì)象,指向當(dāng)前數(shù)據(jù)結(jié)構(gòu)的起始位置
- b 第一次調(diào)用對(duì)象的next方法,指針自動(dòng)指向數(shù)據(jù)結(jié)構(gòu)的第一個(gè)成員
- c 接下來(lái)不斷調(diào)用next方法,指針一直往后移動(dòng),直到指向最后一個(gè)成員
- d 每調(diào)用next方法返回一個(gè)包含value和done屬性的對(duì)象
自定義遍歷數(shù)據(jù)的時(shí)候,要想到迭代器
12.生成器函數(shù)的聲明與調(diào)用
生成器函數(shù)是ES6提供的一種異步編程解決方案,與傳統(tǒng)函數(shù)完全不同,就是一個(gè)特殊的函數(shù)
// 聲明
function * gen(){// * 可以靠左,也可以靠右,還可以放在中間
// console.log('hello');
yield '2020lpl牛批';// yield 語(yǔ)句可以算作函數(shù)代碼的分隔符
let two = yield ‘uzi 退役了’;
console.log(two);
yield '湖人總冠軍';
}
// 執(zhí)行
let iterator = gen();
// console.log(iterator);// 返回結(jié)果是一個(gè)迭代器對(duì)象
console.log(iterator.next());// 需要執(zhí)行迭代器對(duì)象中的next()方法,才會(huì)執(zhí)行生成器函數(shù)
console.log(iterator.next());// 每個(gè)next()只會(huì)執(zhí)行里面一個(gè)yield語(yǔ)句,這個(gè)會(huì)輸出 ‘uzi 退役了’
// 傳遞參數(shù) 參數(shù)將作為上一個(gè)yield語(yǔ)句的返回結(jié)果
console.log(iterator.next('AAA'));// 第三次調(diào)用傳遞的參數(shù)將作為第二個(gè)yield 的返回結(jié)果 打印為AAA
// 使用for of循環(huán)遍歷輸出
for(let v of gen()){
console.log(v);// 依次輸出yield語(yǔ)句中的值
}
案例:1s輸出 111 2s輸出 222 3s輸出 333
function one(){
setTimeout(()=>{
console.log('111')
iterator.next();
}, 1000)
}
function two(){
setTimeout(()=>{
console.log('111')
iterator.next();
}, 1000)
}
function three(){
setTimeout(()=>{
console.log('111')
}, 1000)
}
// 生成器函數(shù)
function * gen(){
yield one();
yield two();
yield three();
}
// 調(diào)用生成器函數(shù)
let iterator = gen();
iterator.next();
13.Promise 基本使用
Promise 是一個(gè)構(gòu)造函數(shù),用來(lái)封裝異步操作并可以獲取其成功或失敗的結(jié)果
- 1、 Promise 構(gòu)造函數(shù) Promise(excutor){}
- 2、 Promise.prototype.then 有兩個(gè)參數(shù),兩個(gè)參數(shù)都是函數(shù),
Promise對(duì)象成功狀態(tài)執(zhí)行then中第一個(gè)函數(shù),失敗執(zhí)行第二個(gè)函數(shù)
- 3、 Promise.prototype.catch
// 實(shí)例化
const p = new Promise((resolve, reject) => {
// 通過(guò)resolve,reject這兩個(gè)函數(shù)來(lái)改變Promise對(duì)象的狀態(tài),
// resolve會(huì)改變p的狀態(tài)為成功,reject會(huì)改變p的狀態(tài)為失敗,然后去執(zhí)行then里面的方法
// 執(zhí)行異步操作,以定時(shí)器為例,定時(shí)器也是異步
setTimeout(()=>{
//let data = '異步執(zhí)行成功';
// resolve(data);// 調(diào)用resolve函數(shù), p會(huì)變成一個(gè)成功的狀態(tài),會(huì)執(zhí)行then中的第一個(gè)方法
let err = '執(zhí)行失敗';
reject(err);// 調(diào)用reject函數(shù),p會(huì)變成一個(gè)失敗的狀態(tài),會(huì)執(zhí)行then中的第二個(gè)方法
}, 1000)
})
// 成功會(huì)調(diào)用 promise 對(duì)象 then 方法
p.then(value => {// 成功
// console.log(value);// 控制臺(tái)打?。寒惒綀?zhí)行成功
}, reason => {// 失敗
console.error(reason)
})
Promise.prototype.then 特性
// then方法的返回結(jié)果是Promise對(duì)象,對(duì)象狀態(tài)由回調(diào)函數(shù)的執(zhí)行結(jié)果決定
const p = new Promise((resolve, reject) => {
setTimeout(()=>{
resolve('成功');
reject('失敗');
}, 1000);
});
// then 的返回結(jié)果是一個(gè)Promise對(duì)象,就是result也是一個(gè)Promise對(duì)象,它的狀態(tài)由函數(shù)的執(zhí)行結(jié)果決定的
const result = p.then(value => {
console.log(value);
// 1.如果返回的結(jié)果是 非Promise 類(lèi)型的屬性,狀態(tài)為成功,返回值return 中的值
// 如果不寫(xiě)return,函數(shù)內(nèi)部不寫(xiě)return返回結(jié)果是undefined,也不是Promise對(duì)象,狀態(tài)也是成功
// return 123;
// 2.是 promise 對(duì)象, 該對(duì)象返回的狀態(tài)就決定了then方法返回promise對(duì)象狀態(tài)
return new Promise((resolve, reject)=>{
// resolve('ok');// then方法返回promise對(duì)象狀態(tài)為成功
reject('no');// then方法返回promise對(duì)象狀態(tài)為失敗
})
// 3.拋出錯(cuò)誤 then方法返回promise對(duì)象狀態(tài)為失敗,錯(cuò)誤值為拋出錯(cuò)誤的值
throw new Error('出錯(cuò)了');
}, reason => {
console.err(reason);
});
console.log(result);
// 綜上總結(jié),then方法可以鏈?zhǔn)秸{(diào)用 可以改變回調(diào)域的現(xiàn)象
p.then(value=>{}, reason=>{})
.then(value()=>{}).then();
舉例:多個(gè)請(qǐng)求都返回之后,獲取其中的數(shù)據(jù)
const p = new Promise((resolve, reject)=>{
resolve('第一次返回成功')
});
p.then(value=>{
return new Promise((resolve, reject)=>{
resolve([value, '第二次返回成功'])
});
}).then(value=>{
return new Promise((resolve, reject)=>{
resolve([...value, '第三次返回成功'])
});
}).then(value=>{
console.log(value);// 返回值為三次請(qǐng)求都返回成功以后的值
});
14.集合set
新的數(shù)據(jù)結(jié)構(gòu)Set(集合),它類(lèi)似于數(shù)組,成員的值都是唯一的,集合實(shí)現(xiàn)了iterator接口,所以可以使用擴(kuò)展運(yùn)算符和for of遍歷
集合的屬性和方法
- 1 size 返回集合的元素個(gè)數(shù)
- 2 add 添加一個(gè)新元素,返回當(dāng)前集合
- 3 delete 刪除元素,返回boolean值
- 4 has 檢測(cè)集合中是否包含某個(gè)元素,返回boolean值
- 5 clear 清空
// 聲明
let s = new Set();
let s2 = new Set([1, 2, 3, 6, 7]);
console.log(s2);// 5
s2.add(8);// 添加新元素
console.log(s2);// 輸出 {1, 2, 3, 6, 7, 8}
s2.delete(8);
console.log(s2);// 輸出 {1, 2, 3, 6, 7}
console.log(s2.has(8));// false
// s2.clear();// 清空
let arr = [1, 2, 3, 3, 3, 6, 6, 8];
let arr2 = [1, 3, 6, 7, 8];
// 數(shù)組去重
let result = [...new Set(arr)];
// 交集
let result = [...new Set(arr)].filter(item => new Set(arr2).has(item));
// 并集
let result = [...new Set([...arr, ...arr2])];
// 差集 arr有arr2中沒(méi)有
let result = [...new Set(arr)].filter(item => !(new Set(arr2).has(item)));
15.Map集合
類(lèi)似于對(duì)象,也是鍵值對(duì)的集合,但是 鍵 不限于字符串,各種類(lèi)型的值(包括對(duì)象)都可以當(dāng)作鍵,
map也實(shí)現(xiàn)了 iterator 接口,所以可以使用擴(kuò)展運(yùn)算符和for of進(jìn)行遍歷
- 1 size 返回 Map 的元素個(gè)數(shù)
- 2 set 增加一個(gè)新元素,返回當(dāng)前Map
- 3 get 返回鍵名對(duì)象的鍵值
- 4 has 檢測(cè)Map中是否包含某個(gè)元素,返回boolean值
- 5 clear 清空集合,返回undefined
// 聲明
let m = new Map();
m.set('name', 'zhangning');
m.set('change', function(){console.log('變得更努力')});// 鍵 change 值 一個(gè)function
let key = {company: 'supwisdom'};
m.set(key, [1, 2, 3]);//鍵 對(duì)象 值 數(shù)組
m.size;// 獲取m個(gè)數(shù)
m.delete('name');// 刪除鍵值對(duì)
m.get('change');// 獲取鍵對(duì)應(yīng)的值
// m.clear();// 清空
for(let v of m){console.log(v);}
16.class 類(lèi)
通過(guò)class可以定義類(lèi),新的class寫(xiě)法只是讓對(duì)象原型的寫(xiě)法更加清晰,更像面向?qū)ο缶幊痰恼Z(yǔ)法而已。
- 1 class 聲明類(lèi)
- 2 constructor 定義構(gòu)造函數(shù)初始化
- 3 extends 繼承父類(lèi)
- 4 super 調(diào)用父級(jí)構(gòu)造方法
- 5 static 定義靜態(tài)方法和屬性
- 6 父類(lèi)方法可以重寫(xiě)
es5通過(guò) 構(gòu)造函數(shù)實(shí)例化 對(duì)象的方法
// 人
function People(name, sex) {
this.name = name;
this.sex = sex;
}
// 這個(gè)height這種添加方式是屬于函數(shù)對(duì)象的,不屬于實(shí)例對(duì)象,這樣的屬性稱(chēng)之為靜態(tài)成員
People.height = '180';
People.prototype.height1 = '100';
// 添加方法
People.prototype.play = function(){
console.log('打籃球');
}
let zn = new People('zhangning', '男');
zn.play();// 輸出 打籃球
console.log(zn);
console.log(zn.height);// 輸出 undefined
console.log(zn.height1);// 輸出 100,必須通過(guò)prototype添加才能添加到實(shí)例對(duì)象上
通過(guò)class實(shí)現(xiàn)
class People{
// 靜態(tài)屬性 static,對(duì)于static 標(biāo)注的方法屬于類(lèi),不屬于實(shí)例對(duì)象
static height = '100';
static change(){
console.log('我可以改變世界');
}
// 構(gòu)造方法 名字不能更改(在使用new People的時(shí)候會(huì)自動(dòng)執(zhí)行實(shí)例對(duì)象上的constructor方法)
constructor(name, sex){
this.name = name;
this.sex = sex;
}
// 添加方法必須使用該語(yǔ)法,不能使用es5的完整形式(play: function(){} 這種形式不支持,必須使用play()形式)
// 成員屬性
play(){
console.log('打籃球');
}
}
let zn = new People('zhangning', '男');
console.log(zn);
console.log(zn.height);// undefined static 標(biāo)注的方法屬于類(lèi),不屬于實(shí)例對(duì)象
console.log(People.height);// 100
使用es5構(gòu)造函數(shù)實(shí)現(xiàn)繼承
// 舉例 chinese 繼承 People 屬性
function People(name, sex) {
this.name = name;
this.sex = sex;
}
People.prototype.play = function(){
console.log('打LOL');
}
function Student(name, sex, like, height){
// 通過(guò)call方法,改變this值,this指向chinese中的this,也就是chinese的一個(gè)實(shí)例對(duì)象
People.call(this, name, sex);
this.like = like;
this.height = height;
}
// 設(shè)置子集構(gòu)造函數(shù)原型
Student.prototype = new People;// 這樣就會(huì)有父級(jí)的一個(gè)方法
Student.prototype.constructor = Student;// 做一個(gè)校正,沒(méi)有這行代碼也無(wú)所謂
// 聲明子類(lèi)方法
Student.prototype.photo = function(){
console.log('去拍照');
}
// 實(shí)例化
const zn = new Student('zhangning', '男', '打籃球', '187');
console.log(zn)
使用es6 class 類(lèi) 實(shí)現(xiàn)繼承 及 父類(lèi)方法的重寫(xiě)
// 聲明父類(lèi)
class People{
// 父類(lèi)構(gòu)造方法
constructor(name, sex) {
this.name = name;
this.sex = sex;
}
// 父類(lèi)成員屬性
play(){
console.log('打LOL');
}
}
// 聲明子類(lèi) 使用extends 繼承父類(lèi)
class Student extends People {
// 構(gòu)造方法
constructor(name, sex, like, height){
super(name, sex);// super 就是父類(lèi)的constructor構(gòu)造函數(shù),這樣調(diào)用
this.like = like;
this.height = height;
}
photo(){
console.log('去拍照');
}
// 對(duì)父類(lèi)中的play方法進(jìn)行重寫(xiě),子類(lèi)是不能去調(diào)用父類(lèi)的同名方法的,
play(){
// super(); 不允許,在普通的成員方法里面是不能出現(xiàn)super()去調(diào)用父類(lèi)的同名方法的,會(huì)報(bào)錯(cuò),只能完全重寫(xiě)
console.log('我會(huì)打LOL,還會(huì)打籃球');
}
}
const zn = new Student('zhangning', '男', '打籃球', '187');
console.log(zn)
class 中 getter 和 setter 設(shè)置
class People{
get like(){
return '打籃球';
}
set like(newVal){
// 通過(guò)傳過(guò)來(lái)的newVal值,進(jìn)行操作,改變 like
console.log('改變like值');
}
}
let p = new People();
console.log(p.like)// 輸出 打籃球
p.like = 'LOL';// 然后通過(guò) set like 進(jìn)行操作
17.對(duì)象數(shù)值擴(kuò)展
Object.is
判斷兩個(gè)值是否完全相等
Object.is(1, 1);// true
和 === 很相似,唯一區(qū)別就是 NaN === NaN 為 false, Object.is(NaN, NaN) 為true
Object.assign
對(duì)象的合并
const c1 = {name: 'znn'};
const c2 = {name: 'zhangning', height: 187};
Object.assign(c1, c2);// 如果兩個(gè)對(duì)象中存在相同屬性,c2 中覆蓋c1中的屬性?xún)?nèi)容
Object.setPrototypeOf
設(shè)置原型對(duì)象
const zn = {
name: 'zhangning',
}
const p = {
h: true,
sfsfdf: 'fasfasdf'
}
Object.setPrototypeOf(zn, p);// 設(shè)置 zn 的原型里面有 p
Object.getPrototypeOf(zn);// 獲取 zn 的原型
console.log(zn);// 打印看下
18.數(shù)組擴(kuò)展
Array.from()
Array.from方法用于將兩類(lèi)對(duì)象轉(zhuǎn)為真正的數(shù)組:類(lèi)數(shù)組的對(duì)象( array-like object )和可遍歷( iterable )的對(duì)象(包括 ES6 新增的數(shù)據(jù)結(jié)構(gòu) Set 和Map )。
let arrayLike = {
'0': 'a',
'1': 'b',
'2': 'c',
length: 3
};
// ES5 的寫(xiě)法
var arr1 = [].slice.call(arrayLike); // ['a', 'b', 'c']
// ES6 的寫(xiě)法
let arr2 = Array.from(arrayLike); // ['a', 'b', 'c']
// NodeList 對(duì)象
let ps = document.querySelectorAll('p');
Array.from(ps).forEach(function (p) {
console.log(p);
});
// arguments 對(duì)象
function foo() {
var args = Array.from(arguments);
// ...
}
//字符串轉(zhuǎn)換為字符數(shù)組str.split('')
Array.from('hello') // ['h', 'e', 'l', 'l', 'o']
let namesSet = new Set(['a', 'b'])
Array.from(namesSet) // ['a', 'b']
Array.from({ length: 3 }); // [ undefined, undefined, undefined ]
對(duì)于還沒(méi)有部署該方法的瀏覽器,可以用Array.prototype.slice方法替代:
const toArray = (() =>
Array.from ? Array.from : obj => [].slice.call(obj)
)();
Array.from還可以接受第二個(gè)參數(shù),作用類(lèi)似于數(shù)組的map方法,用來(lái)對(duì)每個(gè)元素進(jìn)行處理,將處理后的值放入返回的數(shù)組。
Array.from(arrayLike, x => x * x);
// 等同于
Array.from(arrayLike).map(x => x * x);
Array.from([1, 2, 3], (x) => x * x)
// [1, 4, 9]
//Array.from回調(diào)函數(shù)
var arr1 = Array.from([1,2,3], function(item){
return item*item;
});
var arr2 = Array.from([1,2,3]).map(function(item){
return item*item;
});
var arr3 = Array.from([1,2,3], (item) => item*item);
console.log(arr1); //[ 1, 4, 9 ]
console.log(arr2); //[ 1, 4, 9 ]
console.log(arr3); //[ 1, 4, 9 ]
值得提醒的是,擴(kuò)展運(yùn)算符(...)也可以將某些數(shù)據(jù)結(jié)構(gòu)轉(zhuǎn)為數(shù)組。
// arguments 對(duì)象
function foo() {
var args = [...arguments];
}
// NodeList 對(duì)象
[...document.querySelectorAll('div')]
Array.of()
Array.of方法用于將一組值,轉(zhuǎn)換為數(shù)組。Array.of總是返回參數(shù)值組成的數(shù)組。如果沒(méi)有參數(shù),就返回一個(gè)空數(shù)組。
Array.of基本上可以用來(lái)替代Array()或new Array(),并且不存在由于參數(shù)不同而導(dǎo)致的重載。它的行為非常統(tǒng)一。
這個(gè)方法的主要目的,是彌補(bǔ)數(shù)組構(gòu)造函數(shù)Array()的不足。因?yàn)閰?shù)個(gè)數(shù)的不同,會(huì)導(dǎo)致Array()的行為有差異
Array() // []
Array(3) // [, , ,]
Array(3, 11, 8) // [3, 11, 8]
Array.of() // []
Array.of(3) // [3]
Array.of(3, 11, 8) // [3,11,8]
Array.of(3).length // 1
Array.of(undefined) // [undefined]
Array.of(1) // [1]
Array.of(1, 2) // [1, 2]
Array.of方法可以用下面的代碼模擬實(shí)現(xiàn):
function ArrayOf(){
return [].slice.call(arguments);
}
find() 和 findIndex()
數(shù)組實(shí)例的find方法,用于找出第一個(gè)符合條件的數(shù)組成員。它的參數(shù)是一個(gè)回調(diào)函數(shù),所有數(shù)組成員依次執(zhí)行該回調(diào)函數(shù),直到找出第一個(gè)返回值為true的成員,然后返回該成員。如果沒(méi)有符合條件的成員,則返回undefined。
[1, 4, -5, 10].find((n) => n < 0)
// -5
[1, 5, 10, 15].find(function(value, index, arr) {
return value > 9;
}) // 10
上面代碼中,find方法的回調(diào)函數(shù)可以接受三個(gè)參數(shù),依次為當(dāng)前的值、當(dāng)前的位置和原數(shù)組。數(shù)組實(shí)例的findIndex方法的用法與find方法非常類(lèi)似,返回第一個(gè)符合條件的數(shù)組成員的位置,如果所有成員都不符合條件,則返回-1。
[1, 5, 10, 15].findIndex(function(value, index, arr) {
return value > 9;
}) // 2
這兩個(gè)方法都可以接受第二個(gè)參數(shù),用來(lái)綁定回調(diào)函數(shù)的this對(duì)象。
另外,這兩個(gè)方法都可以發(fā)現(xiàn)NaN,彌補(bǔ)了數(shù)組的IndexOf方法的不足。
[NaN].indexOf(NaN)
// -1
[NaN].findIndex(y => Object.is(NaN, y))
// 0
fill()
fill()方法使用給定值,填充一個(gè)數(shù)組。
['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']
上面代碼表明,fill方法用于空數(shù)組的初始化非常方便。數(shù)組中已有的元素,會(huì)被全部抹去。
fill()方法還可以接受第二個(gè)和第三個(gè)參數(shù),用于指定填充的起始位置和結(jié)束位置
['a', 'b', 'c'].fill(7, 1, 2)
// ['a', 7, 'c']
entries() , keys() 和 values()
ES6 提供三個(gè)新的方法 —— entries(),keys()和values() —— 用于遍歷數(shù)組。它們都返回一個(gè)遍歷器對(duì)象,可以用for...of循環(huán)進(jìn)行遍歷,唯一的區(qū)別是keys()是對(duì)鍵名的遍歷、values()是對(duì)鍵值的遍歷,entries()是對(duì)鍵值對(duì)的遍歷。
for (let index of ['a', 'b'].keys()) {
console.log(index);
}
// 0
// 1
for (let elem of ['a', 'b'].values()) {
console.log(elem);
}
// 'a'
// 'b'
for (let [index, elem] of ['a', 'b'].entries()) {
console.log(index, elem);
}
// 0 "a"
// 1 "b"
如果不使用for...of循環(huán),可以手動(dòng)調(diào)用遍歷器對(duì)象的next方法,進(jìn)行遍歷。
let letter = ['a', 'b', 'c'];
let entries = letter.entries();
console.log(entries.next().value); // [0, 'a']
console.log(entries.next().value); // [1, 'b']
console.log(entries.next().value); // [2, 'c']
includes()
ES5中,我們常用數(shù)組的indexOf方法,檢查是否包含某個(gè)值。indexOf方法有兩個(gè)缺點(diǎn),一是不夠語(yǔ)義化,它的含義是找到參數(shù)值的第一個(gè)出現(xiàn)位置,所以要去比較是否不等于 -1 ,表達(dá)起來(lái)不夠直觀。二是,它內(nèi)部使用嚴(yán)格相當(dāng)運(yùn)算符( === )進(jìn)行判斷,這會(huì)導(dǎo)致對(duì)NaN的誤判。
[NaN].indexOf(NaN)
// -1
includes使用的是不一樣的判斷算法,就沒(méi)有這個(gè)問(wèn)題。
[NaN].includes(NaN)
// true
Array.prototype.includes方法返回一個(gè)布爾值,表示某個(gè)數(shù)組是否包含給定的值,與字符串的includes方法類(lèi)似。該方法屬于 ES7 ,但 Babel 轉(zhuǎn)碼器已經(jīng)支持。
[1, 2, 3].includes(2); // true
[1, 2, 3].includes(4); // false
[1, 2, NaN].includes(NaN); // true
該方法的第二個(gè)參數(shù)表示搜索的起始位置,默認(rèn)為 0 。如果第二個(gè)參數(shù)為負(fù)數(shù),則表示倒數(shù)的位置,如果這時(shí)它大于數(shù)組長(zhǎng)度(比如第二個(gè)參數(shù)為 -4 ,但數(shù)組長(zhǎng)度為 3 ),則會(huì)重置為從 0 開(kāi)始。
[1, 2, 3].includes(3, 3); // false
[1, 2, 3].includes(3, -1); // true
下面代碼用來(lái)檢查當(dāng)前環(huán)境是否支持該方法,如果不支持,部署一個(gè)簡(jiǎn)易的替代版本。
const contains = (() =>
Array.prototype.includes
? (arr, value) => arr.includes(value)
: (arr, value) => arr.some(el => el === value)
)();
contains(["foo", "bar"], "baz"); // => false
另外, Map 和 Set 數(shù)據(jù)結(jié)構(gòu)有一個(gè)has方法,需要注意與includes區(qū)分。
Map 結(jié)構(gòu)的has方法,是用來(lái)查找鍵名的,比如Map.prototype.has(key)、WeakMap.prototype.has(key)、Reflect.has(target, propertyKey)。
Set 結(jié)構(gòu)的has方法,是用來(lái)查找值的,比如Set.prototype.has(value)、WeakSet.prototype.has(value)。
數(shù)組的空位
數(shù)組的空位指,數(shù)組的某一個(gè)位置沒(méi)有任何值。比如,Array構(gòu)造函數(shù)返回的數(shù)組都是空位。
注意,空位不是undefined,一個(gè)位置的值等于undefined,依然是有值的??瘴皇菦](méi)有任何值,in運(yùn)算符可以說(shuō)明這一點(diǎn)。
0 in [undefined, undefined, undefined] // true
0 in [, , ,] // false
上面代碼說(shuō)明,第一個(gè)數(shù)組的 0 號(hào)位置是有值的,第二個(gè)數(shù)組的 0 號(hào)位置沒(méi)有值。
ES5 對(duì)空位的處理,已經(jīng)很不一致了,大多數(shù)情況下會(huì)忽略空位。
- forEach() , filter() , every() 和some()都會(huì)跳過(guò)空位。
- map()會(huì)跳過(guò)空位,但會(huì)保留這個(gè)值
- join()和toString()會(huì)將空位視為undefined,而undefined和null會(huì)被處理成空字符串。
// forEach方法
[,'a'].forEach((x,i) => console.log(i)); // 1
// filter方法
['a',,'b'].filter(x => true) // ['a','b']
// every方法
[,'a'].every(x => x==='a') // true
// some方法
[,'a'].some(x => x !== 'a') // false
// map方法
[,'a'].map(x => 1) // [,1]
// join方法
[,'a',undefined,null].join('#') // "#a##"
// toString方法
[,'a',undefined,null].toString() // ",a,,"
ES6則是明確將空位轉(zhuǎn)為undefined。
//Array.from方法會(huì)將數(shù)組的空位,轉(zhuǎn)為undefined,也就是說(shuō),這個(gè)方法不會(huì)忽略空位。
Array.from(['a',,'b']) // [ "a", undefined, "b" ]
//擴(kuò)展運(yùn)算符(...)也會(huì)將空位轉(zhuǎn)為undefined。
[...['a',,'b']] // [ "a", undefined, "b" ]
//copyWithin()會(huì)連空位一起拷貝。
[,'a','b',,].copyWithin(2,0) // [,"a",,"a"]
//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并沒(méi)有忽略它們。如果改成map方法遍歷,空位是會(huì)跳過(guò)的。
//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)空位。
文章來(lái)源于公眾號(hào): 猴哥說(shuō)前端,作者:monkeysoft
以上就是W3Cschool編程獅
關(guān)于****的相關(guān)介紹了,希望對(duì)大家有所幫助。