本文介紹ES6常用擴(kuò)展。
竟然在圖書館借到了想買的ES6入門標(biāo)準(zhǔn),省下一頓多倫多。[捂臉].jpg
一,變量聲明擴(kuò)展
1,let
在ES5聲明變量的方法一直是var,var有著變量提升和全局聲明的特點(diǎn),也因此var聲明的變量本身不存在塊級(jí)作用域。
在ES6的let中,聲明的變量僅在塊級(jí)作用域中有效,且不會(huì)出現(xiàn)變量提升的情況。
var a = []
for(var i = 0 ; i < 10 ; i++){
a[i] = function(){
//此處閉包可以訪問函數(shù)外其他作用域的變量i
//但是此時(shí)的i的值已經(jīng)是10
console.log(i)
}
}
a[3]() //10
以上代碼中由于function中的i,由var定義,沒有塊級(jí)作用域,最終結(jié)果10個(gè)函數(shù)都輸出i的最終值10
var a = []
for(var i = 0 ; i < 10 ; i++){
(function(){
console.log(i)
})(i)
} //輸出1-10
以上代碼模仿塊級(jí)作用域,也可以用閉包返回一個(gè)匿名函數(shù),來實(shí)現(xiàn)塊級(jí)作用域,但是閉包會(huì)導(dǎo)致資源泄漏等問題,需要主動(dòng)釋放資源。
var a = []
for(let i = 0 ; i < 10 ; i++){
a[i] = function(){
console.log(i)
}
}
a[3]() //3
使用let之后,每個(gè)i在都有一個(gè)單獨(dú)的作用域,互相不受影響。
2,const
const用來聲明常量,一旦聲明不可改變。
const聲明的常量也有塊級(jí)作用域
和C里面的DEFINE差不多
3,解構(gòu)賦值
ES6允許按照一定的模式,從數(shù)組和對(duì)象中提取值,對(duì)變量進(jìn)行賦值,這被稱為解構(gòu)
var [a,b] = [1,2]
//按照對(duì)應(yīng)的關(guān)系a為1,b為2
var [a,...b] = [1,2,3,4,5]
//a為1,b為數(shù)組形式[2,3,4,5]
//除了解構(gòu)數(shù)組還能解構(gòu)對(duì)象
var {foo,bar} = {foo:"aaa",bar:"bbb"}
console.log(foo) //"aaa"
console.log(bar) //"bbb"
//加載模塊時(shí),經(jīng)常使用這種方法,可以準(zhǔn)確地在對(duì)應(yīng)模塊中獲取對(duì)應(yīng)的參數(shù)
const {SourceMapConsumer,SourceNode} = require("source-map");
tip:使用如[x,y] = [y,x]可以交換變量的值
二,字符串?dāng)U展
1,includes、repeat、startsWith、endsWith
[1,2,3,4].includes(2)
//返回true
includes包含,若字符串/數(shù)組中包含所輸入字符,則返回true,否則返回false
ES5中常用indexOf(),若包含字符所輸則返回字符在字符串/數(shù)組中所在的位置,若不存在則返回-1
'abc'.startsWith('a') //true
'abc'.endsWith('c') //true 如其名= =
"x".repeat(3) //repeat接收一個(gè)number參數(shù),返回一個(gè)此字符串重復(fù)n次的字符串,此處返回xxx
2,模板字符串
個(gè)人感覺,模板字符串的好處在于寫前端代碼需要寫大量字符串拼接時(shí)可以使用,減少代碼量。模板字符串用``反引號(hào)包裹,需要引用的變量用${x}包裹。
var x = 1,y = 2
console.log(`${x}+${y}=${x+y}`)
//1+2=3
三,數(shù)組的擴(kuò)展
1,Array.from()
一行數(shù)組去重讓我記憶猶新
console.log(Array.from(new Set([1,2,3,4,2,1])))
//[1, 2, 3, 4]
Array.from()可以將類數(shù)組和可遍歷的對(duì)象轉(zhuǎn)化為真正的數(shù)組
類數(shù)組,如Map,Set這種類型,本身無法調(diào)用數(shù)組的api,經(jīng)Array.from()轉(zhuǎn)化之后即可使用.
2,find()和findIndex()
數(shù)組實(shí)例的find用于找出第一個(gè)符合條件的數(shù)組函數(shù),而findindex用于找出第一個(gè)符合條件的數(shù)組,兩個(gè)函數(shù)的參數(shù)都是一個(gè)回調(diào)函數(shù),所有元素會(huì)依次遍歷該回調(diào)函數(shù)。該回調(diào)函數(shù)接收三個(gè)參數(shù)function(value,index,arr){}分別是當(dāng)前的值、當(dāng)前的位置、還有原數(shù)組。
[11,23,32,44,51].find(function(value,index,arr){
if(value%2==0){
return value
}
}) //返回第一個(gè)除以2余數(shù)為0的value,即32
[11,23,32,44,51].findIndex(function(value,index,arr){
if(value%2==0){
return value
}
})//如果換成findIndex,則返回第一個(gè)除以2為0的value的下標(biāo),即2
3,數(shù)組實(shí)例的entries(),keys(),values()
這三個(gè)方法都返回一個(gè)數(shù)組的迭代器Array Iterator {},可以通過遍歷獲取其中的鍵值。
在ES5中對(duì)數(shù)組常用forEach遍歷,得到數(shù)組的value/鍵值,而for...in獲取數(shù)組的index序號(hào)/鍵名
而for...of始終用于獲取值
這三個(gè)方法將其完全分隔,當(dāng)需要獲取該數(shù)組的鍵時(shí)使用keys(),需要獲取值時(shí)使用values(),需要獲取鍵值對(duì)則使用entries()。
var arr = ['a','b']
for(let index of arr.keys()){
console.log(index)
//返回arr的鍵位0,1
}
for(let item of arr.values()){
console.log(item)
//返回arr的值位a,b
}
for(let [index,item] of arr.entries()){
console.log(index,item)
//返回arr的鍵值index分別為0,1,item分別為a,b
}
對(duì)數(shù)組的所有類型的遍歷上述方法都能實(shí)現(xiàn),且代碼更規(guī)范清晰。
四,對(duì)象的擴(kuò)展
1,Object.assign()
Object.assign()接受兩個(gè)參數(shù),可以實(shí)現(xiàn)引用類型的深拷貝
var a = [1,2]
var copy = []
Object.assign(copy,a)
copy.push(3)
console.log(copy,a)
// (3) [1, 2, 3]
// (2) [1, 2]
// 對(duì)copy新增的數(shù)據(jù)并沒有影響a
2,Object.setPrototypeOf(),Object.getPrototypeOf()
分別用于設(shè)置和獲取對(duì)象proto指向的原型
tip : ES5的Object.creat()也可以動(dòng)態(tài)設(shè)置對(duì)象的原型,此處為創(chuàng)建
3,Symbol
JS基本類型再添一員
1,Undefined 未定義
2,Null 空值
3,Boolean 布爾類型
4,Number 數(shù)字類型
5,String 字符串類型
6,Array 數(shù)組類型
7,Symbol 獨(dú)一無二的類型
ES6書寫Symbol類型可以通過.name獲取其描述值,親測不行= =
Symbol數(shù)據(jù)通過Symbol函數(shù)創(chuàng)建
var mySymbol = Symbol('cty')
此mySymbol是獨(dú)一無二的,即使再創(chuàng)建一個(gè)mySymbol2有同樣描述
mySymbol == mySymbol //false
4,Object.observe()和Object.unobserve()
用于監(jiān)聽一個(gè)對(duì)象的改變Object.observe(o,observer) //observer為改變時(shí)的回調(diào)
但是此提案已被撤回,類似的功能還有攔截代理proxy。待續(xù)
五,函數(shù)的擴(kuò)展
1,擴(kuò)展運(yùn)算符...
與結(jié)構(gòu)賦值相似,在函數(shù)參數(shù)中的...argument代表一個(gè)參數(shù)序列
function(...s){
//s可以是任意長度的字符串
console.log(s)
}
2,箭頭函數(shù)
箭頭函數(shù)只能在函數(shù)內(nèi)部使用,因?yàn)槠浔旧頉]有this域,它的this代表的是最近的,定義的構(gòu)造函數(shù)所在的對(duì)象。使用示例:
var result = values.sort((a,b)=>{return a - b})
3,Generator遍歷器
Generator函數(shù)與普通函數(shù)只有稍許差別,一是,function關(guān)鍵字后面帶有一個(gè)號(hào);二是函數(shù)體內(nèi)部使用yield*語句定義遍歷器的每個(gè)成員。
function* echoHello(){
yield 'hello'
yield '。'
return ’ending‘
}
var eH = echoHello() //儲(chǔ)存echoHello函數(shù),此時(shí)echoHello函數(shù)并不執(zhí)行,而是返回了一個(gè)遍歷器,此步是必要的
//之后每次對(duì)此遍歷器執(zhí)行.next操作,如果碰到y(tǒng)ield語句,則暫停執(zhí)行,并返回一個(gè)帶返回值和執(zhí)行是否結(jié)束的標(biāo)志done
eH.next()
//{ value: 'hello' , done: false }
eH.next()
//{ value:'。' , done: false }
eH.next()
//{ value:'ending' , done: true }
eH.next()
//{ value:undefined , done:true }
generate的此種特性可以用來執(zhí)行異步操作,因?yàn)?next()操作是同步執(zhí)行,js又是單線程的,上一個(gè).next方法未結(jié)束時(shí),下一個(gè).next方法并不會(huì)執(zhí)行,只需要將任務(wù)順序按次序在generate中排好即可。
4,promise對(duì)象
promise承諾,通過.then的鏈?zhǔn)秸{(diào)用避免了回調(diào)地獄,使異步操作更優(yōu)雅,清晰
//以下新建一個(gè)promise對(duì)象
var promise = new Promise((resolve,reject)=>{
if(/*異步操作成功*/){
resolve(value)
}else{
//拋出錯(cuò)誤
reject(error)
}
})
promise.then(value=>{ //success }).catch(err=>{ //error })
用promise實(shí)現(xiàn)原生ajax請(qǐng)求
var getJSON = function(url){
var promise = new Promise(function(resolve,reject){
var xhr = new XMLHttprequest()
xhr.open("POST",url,false)
xhr.onreadychange = function(){
if(this.readyState == 4){
if(this.status == 200){
//此處res是后端規(guī)定的返回對(duì)象
resolve(this.res)
}else{
reject(this)
}
}
}
xhr.send()
return promise //返回promise對(duì)象
})
}
getJSON('/post.json').then(function(json){
// 此處的json為getJSON函數(shù)返回的promise的resolve中所傳遞的返回值
//ajax請(qǐng)求成功后的后續(xù)操作
}).catch(function(err){
//失敗操作
})
在傳遞成功后可以繼續(xù)使用鏈?zhǔn)秸{(diào)用但是要保證給then方法傳遞的是一個(gè)promise對(duì)象,才可以繼續(xù)執(zhí)行.then操作,否則鏈?zhǔn)秸{(diào)用會(huì)中斷。
5,class和extends
類和繼承
class animals(){
//此處還是創(chuàng)建了構(gòu)造函數(shù)
constructor(name){
this.name = name
this.say = function(){
console.log(this.name)
}
}
}
var cat = new animals('miaomiao') //class類只能通過new來調(diào)用,產(chǎn)生一個(gè)這個(gè)類的實(shí)例
cat.say() //miaomiao
經(jīng)檢測,animals.prototype.constructor == animals 返回true
typeof animals 返回function
每個(gè)class和class原型的constructor都是相等的,且每個(gè)class都是function
//此部分展示getter和setter的使用
class Class2{
get name(){
return 'jay';
}
set name(value){
console.log('set name = ' + value);
}
}
var c2 = new Class2();
c2.name = 'hu'; // "set name = hu" 設(shè)置時(shí)會(huì)觸發(fā)class中的set函數(shù)
console.log(c2.name); // "jay" //獲取時(shí)返回get中預(yù)先設(shè)置的值
繼承
在ES5中,沒有extend的幫助,采用的原型繼承,使子類的原型對(duì)象成為父類的一個(gè)實(shí)例,子類中的prototype指針即指向了父類,再在子類的構(gòu)造函數(shù)中動(dòng)態(tài)調(diào)用父類的構(gòu)造函數(shù)解決引用類型互相影響的現(xiàn)象,俗稱組合繼承。
如今
class cat extends animals{
constructor(character){
super(name) //子類中動(dòng)態(tài)調(diào)用父類的構(gòu)造函數(shù)
this.char = character
}
}
var myCat = new cat('miaomiao','quit')
myCat.say() //miaomiao
console.log(myCat.char) //quit
通過extends關(guān)鍵字,引入了子類父類的區(qū)別,類似于組合繼承,依然沒有完全脫離原型鏈的思想。
ES6語法寫到這里,以后踩坑了再來補(bǔ)充把0.0
陳小源 2017/10/20