ES6個人總結
一.模板字符串
基本用法和好處
比如聲明一個變量,以前是用單引號或者用雙引號來把字符串包起來
這兩種方式
var name ="小明"
var sex = '男'
現在可以用模板字符串(反引號) ``
這樣
var name= `小明`
好處是不再需要用+號來拼接字符串
例如
之前拼接的做法
var name ='小明'
console.log('我是'+name+',而且很帥')
現在使用模板字符串
var name =-'小明'
console.log(`我叫${name},而且很帥`)
當然,少量的代碼是看不出方便之處的,當你在做一個很長的字符串拼接的時候就會感覺到,用模板字符串就很快的拼接完了.
二.解構賦值
1.對象解構
var obj={name:"張三",age:18}
var {name,age}=obj;
下面的對象裏面生成2個變量,name值來自於obj.name、age值來自於obj.age
2.數組解構
因爲數組是有順序的一組數據.所以,要一 一對應起來,如果沒有就返回undefined
var [name, age, sex] = ['小明', 14, '男']
數組也可以嵌套比如
var [cat, [name, age], sex] = ['小貓', ['旺財', 2], '女']
var [name, age, sex] = ['小明', 14,]
這裏輸出sex的時候返回的是undefined
注意:數組的元素是有順序的,變量的取值由數組中元素的位置決定;而對象的屬性沒有序,但是變量必須與屬性同名,才能取到正確的值。
3.函數的參數解構
聲明一個fn函數,函數的參數是一個對象,把它傳進去
function fn(obj){
console.log(obj.age); //5
console.log(obj.height) //180
}
fn({age:5,height:180})
//等價於
function fn({ age,height }){
console.log(age); //5
console.log(height) //180
}
fn({age:5,height:180})
三.函數rest參數
在es6中,函數給我們提供了一個參數,跟arguments參數差不多
但是arguments是僞數組,而rest是真數組,這個rest參數我們用(…args)來表示
例如
function fn (...args){
console.log(...args) //[1,2,3,4,5]
}
fn(1,2,3,4,5)
這樣就可以直接使用數組裏面的方法.
四.箭頭函數
1.基本用法
普通匿名函數例如
div.onclick =function(){
console.log('這是普通匿名函數')
}
箭頭函數的寫法
div.onclick =()=>{
console.log('這是箭頭函數')
}
有一個參數的寫法
div.onclick =(n)=>{
console.log('這是箭頭函數')
}
也可以這樣寫 是等價的
div.onclick =n=>{
console.log('這是箭頭函數')
}
有2個及更多參數的箭頭函數
var fn=(a,b,c)=>{
console.log("這是箭頭函數")
}
2.與普通匿名函數的區別
1,箭頭函數體內的this對象,就是定義時所在的對象,而不是使用時所在的對象。
也就是說
用箭頭函數
div.onclick =()=>{
console.log(this) //window
}
不用箭頭函數
div.onclick =function (){
console.log(this) //指向的是當前調用它的對象
}
2,不可以當作構造函數,也就是說,不可以使用new命令,否則會拋出一個錯誤。
3,不可以使用arguments對象,該對象在函數體內不存在。如果要用,可以用 rest 參數代替。
應用場景
按鈕組件點擊,有各自不同而操作
首先不用箭頭函數
爲了方便觀察把代碼放在一起,現在我需要點擊按鈕,一秒後禁用.
<button>提交1</button>
<button>提交2</button>
<button>提交3</button>
<button>提交4</button>
<button>提交5</button>
<button>提交6</button>
var btn = document.querySelectorAll('button')
for (let i = 0; i < btn.length; i++) {
btn[i].onclick = function() {
var that=this;
setTimeout(function() {
that.disabled = true;
}, 1000);
}
}
因爲定時器裏面的回調函數是指向window的所以,要在定時器的外面,聲明一個變量that,把當前的作用域存在that裏面,然後在定時器裏面使用,這樣才行
用箭頭函數
for (let i = 0; i < btn.length; i++) {
btn[i].onclick = function() {
因爲箭頭函數裏面的沒有自己的this 都是指向定義時的所在的作用域
setTimeout(() => {
console.log(this); //指向當前調用它的那個對象
this.disabled = true;
}, 3000);
}
}
這時就不需要保存作用域了,是不是方便了許多
當然,還有很多應用場景的,我這裏只是舉個例子而已.
五.Promise
1.基本用法
把異步操作封裝在一個promise對象中
function fn(){
return new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log('執行操作')
這裏是爲了告訴外界這一步操作已經完成,可以繼續執行下一步
resolve();
},1000);
})
}
調用fn
fn().then(()=>{
這裏執行開始下一步
console.log('下一步操作')
})
promise中有兩個參數,resolve和reject
這兩個參數的含義是
執行了resolve()表示異步操作是成功的
執行了reject()表示異步操作是失敗的
2.傳參
function fn(){
return new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log('執行操作')
resolve('執行完成');
},1000);
})
}
res就表示上一個異步操作返回的參數值,可以是返回值,也可以是字符串
如果用異步操作來請求服務器數據,這裏的res就表示從服務器中我獲取到的數據
fn().then((res)=>{
這裏執行開始下一步
console.log(res) //執行完成
console.log('下一步操作')
})
3.錯誤處理
捕捉錯誤可以用catch來捕捉異步回調中發生的錯誤
function f1(name){
return new Promise((resolve,reject)=>{
setTimeout(()=>{
if(name=="abc"){
resolve("成功了");
}else{
reject("失敗了")
}
},1000)
})
}
f1('abc').then((res)=>{
console.log(res) //成功了
var a=3;
a() //這裏發生了錯誤,因爲a不是函數
用catch可以捕獲到回調中發生的錯誤
}).catch(res={
console.log(res) //a is not a function
})
4.作用
promise可以解決回調地獄的問題,
回調地獄就是不停的回調,
就像if條件判斷,很多個條件判斷語句,這樣不但會變成回調地獄,代碼看起來也很不順眼
if(){
if(){
if(){
if(){}
}
}
}
或者ajax請求路徑下面文件的數據,
$.get("/a",function(res){
$.get("/a/b",function(){
$.get("/a/b/c",function(){
$.get("/a/b/c/d",function(){
//...
})
})
})
})
又或者在node開發:開個服務器、接收一個請求、請求路徑、訪問數據庫,讀取文件;
這些都是異步操作,容易形成回調地獄
所以我們就需要promise來解決這個問題
function fn1(){
return new Promise(resolve=>{
setTimeout(()=>{
console.log('第一步');
異步邏輯已經執行完,必須要告訴外界我執行完了
resolve('第一步執行完成');
},1000)
})
}
function fn2(){
return new Promise(resolve=>{
setTimeout((res)=>{
console.log('第二步');
//告訴外界我執行完了
resolve('第二步執行完成');
},1000)
})
}
fn1().then(res=>{
console.log(res)
//返回一個promise對象
return fn2();
}).then(res=>{
console.log(res)
return fn1();
}).then(res=>{
console.log(res)
return fn2();
}).then(res=>{
console.log(res)
setTimeout(()=>{
console.log('完成');
},1000)
})
輸出的順序是 第一步-第一步完成----第二步-第二步完成----第一步-第一步完成----第二步-第二步完成----完成
六.async(其實是Promise的語法糖)
await可以執行異步操作,但是await必須在async函數內執行
1.用法
先封裝好一個promise
function f1(){
return new Promise(resolve=>{
setTimeout(()=>{
console.log('執行操作');
告知外界執行結束
resolve('over');
},1000);
})
}
(async function(){
await f1(); 表示這是異步操作,下面的代碼會在執行完這個異步操作後才執行
說白了,就是執行了resolve()
console.log('第二步');
await f1();
await f1();
console.log('第三步');
})()
await操作可以有返回值,這個返回值表示promise操作成功的返回值,
如果需要用到返回值,可以聲明一個變量去接受,然後在使用這個返回值
就像這樣 var a = await f1( ) 這時候就可以使用await的返回值了.
2.錯誤處理
如果await裏面執行的異步操作發生了reject,或者發生了錯誤,那麼只能使用try…catch語法來進行錯誤處理
比如
function f1(){
return new Promise((resolve,rejeck)=>{
setTimeout(()=>{
console.log('執行操作')
rejeck('出錯了');
},1000);
})
}
(async function(){
try{
用a來接受rejeck返回的結果
var a = await f1()
console.log(a) //出錯了
}catch(e){
console.log(e)
}
})()
在實際開發過程中一般用異步操作都是成功的,拿到返回值然後再進行下一步操作,因爲不可能失敗了還繼續讓程序運行下去的.
七.class 類
1.用法
定義一個類
class father (){
constructor(name) {
this.name=name;
}
}
var f1= new father('小明')
其實這個就相當與構造函數,只不過換了一種寫法
function father (name){
this.name=name;
}
如果我們需要添加實例方法
class father (){
constructor(name) {
this.name=name;
}
定義方法
say(){
console.log(`我會說話,我的名字叫${this.name}`)
}
2.添加靜態方法
添加靜態方法
class father (){
constructor(name) {
this.name=name;
}
static say(){
console.log(`我會說話,我的名字叫${this.name}`)
}
訪問靜態方法
father.say()
這個say方法就是一個靜態方法
- 靜態成員:靜態屬性、靜態方法
- 靜態屬性:通過類本身來訪問:father.name
- 靜態方法:通過類本身來訪問的一個方法:father.say()
3.類的繼承(extends)
在es6中有extends,所以讓我們的繼承就方便了很多
先創建一個父類
class Father(){
constructor (name,age){
this.name=name
this.age=age
}
}
子類繼承父類 這裏面 須調用父類構造方法,如果不調用就會報錯
class Sun extends Father {
constructor(name, sex) {
super(name);
調用父類構造方法,從而給子類的實例添加了name屬性
this.sex = sex;
}
}
var sun =new Sun('小明','男')
console.log (sun) //sun:{name:'小明',sex:'男'}
這裏的name屬性是繼承了父類裏面的name屬性
super關鍵字的作用
super關鍵字是在子類對象內部指代其父類對象的引用
八.對象擴展運算符(…)
var obj1= {name:'小明',age:13}
var obj2={...obj1}
console.log(obj2) // {name:'小明',age:13}
也可以添加其他屬性和修改拷貝過來的屬性
var obj1= {name:'小明',age:13}
var obj2={...obj1}
var obj3 = {...obj1,age:11,sex:'男'}
console.log(obj2) // {name:'小明',age:13}
console.log(obj3) // {name:'小明',age:11,sex:''男'}
console.log(obj1) // {name:'小明',age:13}
方便很多,以前要實現拷貝還要遍歷然後在把數組或者對象添加進來才能實現拷貝繼承,現在用對象擴展運算符很快就拷貝好了.
作用
實現拷貝繼承,當然了只是淺拷貝而已,實現深拷貝的話就要(淺拷貝+遞歸),當然也有其他方法實現深拷貝(這裏就不說這麼多)