ES6特性總結
點擊上方藍色字體,選擇“置頂或者星標”?
優(yōu)質文章第一時間送達!
ES6特性總結
簡介
ECMAScript6.0(以下簡稱ES6,ECMAScript是一種由Ecma國際(前身為歐洲計算機制造商協(xié)會,英文名稱是EuropeanComputerManufacturersAssociation)通過ECMA-262標準化的腳本程序設計語言)是JavaScript語言的下一代標準,已經(jīng)在2015年6月正式發(fā)布了,并且從ECMAScript6開始,開始采用年號來做版本。即ECMAScript2015,就是ECMAScript6。它的目標,是使得JavaScript語言可以用來編寫復雜的大型應用程序,成為企業(yè)級開發(fā)語言。每年一個新版本。

什么是ECMAScript
來看下前端的發(fā)展歷程:
web1.0時代:
最初的網(wǎng)頁以HTML為主,是純靜態(tài)的網(wǎng)頁。網(wǎng)頁是只讀的,信息流只能從服務的到客戶端單向流通。開發(fā)人員也只關心頁面的樣式和內容即可。
web2.0時代:
1995年,網(wǎng)景工程師BrendanEich花了10天時間設計了JavaScript語言。 1996年,微軟發(fā)布了JScript,其實是JavaScript的逆向工程實現(xiàn)。 1996年11月,JavaScript的創(chuàng)造者Netscape公司,決定將JavaScript提交給標準化組織ECMA,希望這種語言能夠成為國際標準。 1997年,ECMA發(fā)布262號標準文件(ECMA-262)的第一版,規(guī)定了瀏覽器腳本語言的標準,并將這種語言稱為ECMAScript,這個版本就是1.0版。JavaScript和JScript都是 ECMAScript的標準實現(xiàn)者,隨后各大瀏覽器廠商紛紛實現(xiàn)了ECMAScript標準。
所以,ECMAScript是瀏覽器腳本語言的規(guī)范,而各種我們熟知的js語言,如JavaScript則是規(guī)范的具體實現(xiàn)。
ES6新特性
1. let聲明變量
??//var聲明的變量往往會越域
??//let聲明的變量有嚴格局部作用域
??{
????var?a?=?1;
????let?b?=?2;
??}
??console.log(a);?//1
??console.log(b);?//ReferenceError:bisnotdefined
??
??
??//var可以聲明多次
??//let只能聲明一次
??var?m?=?1
??var?m?=?2
??let?n?=?3
??//let?n?=?4
??console.log(m)?//2
??console.log(n)?//Identifier'n'hasalreadybeendeclared
??
??//var會變量提升
??//let不存在變量提升
??console.log(x);?//undefined
??var?x?=?10;
??console.log(y);?//ReferenceError:yisnotdefined
??let?y?=?20;
2. const聲明常量(只讀變量)
??//1.聲明之后不允許改變
??//2.一但聲明必須初始化,否則會報錯
??const?a?=?1;
??a?=?3;??//UncaughtTypeError:Assignmenttoconstantvariable.
3. 解構表達式
數(shù)組結構
let?arr?=?[1,?2,?3];
//以前我們想獲取其中的值,只能通過角標。ES6可以這樣:
const?[x,?y,?z]?=?arr;?//x,y,z將與arr中的每個位置對應來取值//然后打印
console.log(x,?y,?z);
對象結構
const?person?=?{
??name:?"jack",
??age:?21,
??language:?['java', 'js', 'css']
}
//解構表達式獲取值,將person里面每一個屬性和左邊對應賦值
const?{name,?age,?language}?=?person;
//等價于下面
//const?name?=?person.name;
//const?age?=?person.age;
//const?language?=?person.language;
//可以分別打印
console.log(name);
console.log(age);
console.log(language);
//擴展:如果想要將name的值賦值給其他變量,可以如下,nn是新的變量名
const?{name:?nn,?age,?language}?=?person;
console.log(nn);
console.log(age);
console.log(language);
4. 字符串擴展
幾個新的API
ES6為字符串擴展了幾個新的API:
includes():返回布爾值,表示是否找到了參數(shù)字符串。startsWith():返回布爾值,表示參數(shù)字符串是否在原字符串的頭部。endsWith():返回布爾值,表示參數(shù)字符串是否在原字符串的尾部。
let?str?=?"hello.vue";
console.log(str.startsWith("hello"));?//true
console.log(str.endsWith(".vue"));?//true
console.log(str.includes("e"));?//true
console.log(str.includes("hello"));?//true
字符串模板
模板字符串相當于加強版的字符串,用反引號`,除了作為普通字符串,還可以用來定義多行字符串,還可以在字符串中加入變量和表達式。
//1、多行字符串
let?ss?=?`
??
???helloworld
??
`
console.log(ss)
//2、字符串插入變量和表達式。變量名寫在${}中,${}中可以放入JavaScript表達式。
let?name?="張三";
let?age?=?18;
let?info?=?`我是${name},今年${age}了`;
console.log(info)
//3、字符串中調用函數(shù)
function?fun()?{
??return"這是一個函數(shù)"
}
let?sss?=?`O(∩_∩)O哈哈~,${fun()}`;
console.log(sss);?//O(∩_∩)O哈哈~,這是一個函數(shù)
5. 函數(shù)優(yōu)化
函數(shù)參數(shù)默認值
//在ES6以前,我們無法給一個函數(shù)參數(shù)設置默認值,只能采用變通寫法:
function?add(a,?b)?{
??//判斷b是否為空,為空就給默認值1
??b?=?b?||?1;
??return?a?+?b;
}
//傳一個參數(shù)
console.log(add(10));
//現(xiàn)在可以這么寫:直接給參數(shù)寫上默認值,沒傳就會自動使用默認值
function?add2(a,?b?=?1)?{
??return?a?+?b;
}
//傳一個參數(shù)
console.log(add2(10));
不定參數(shù)
不定參數(shù)用來表示不確定參數(shù)個數(shù),形如,...變量名,由...加上一個具名參數(shù)標識符組成。具名參數(shù)只能放在參數(shù)列表的最后,并且有且只有一個不定參數(shù)
function?fun(...values){
????console.log(values.length)
}
fun(1,?2)?//2
fun(1,?2,?3,?4)?//4
箭頭函數(shù)
ES6中定義函數(shù)的簡寫方式
一個參數(shù)時:
//以前聲明一個方法
var?print?=?function(obj) {
????console.log(obj);
}
//可以簡寫為:
var?print?=?obj?=>?console.log(obj);
//測試調用
print(100);
多個參數(shù):
//兩個參數(shù)的情況:
var?sum?=?function(a,?b)?{
????return?a + b;
}
//簡寫為:
//當只有一行語句,并且需要返回結果時,可以省略{},結果會自動返回。
var?sum2?=?(a,?b)?=>?a?+?b;
//測試調用
console.log(sum2(10,?10));?//20
//代碼不止一行,可以用`{}`括起來
var?sum3?=?(a,?b)?=>?{
??c?=?a?+?b;
??return?c;
};
//測試調用
console.log(sum3(10,?20));?//30
實戰(zhàn):箭頭函數(shù)結合解構表達式
//需求,聲明一個對象,hello方法需要對象的個別屬性
//以前的方式:
const?person?=?{
??name:?"jack",
??age:?21,
??language:?['java',?'js',?'css']
}
function?hello(person)?{
?console.log("hello,?"?+?person.name)
}
//現(xiàn)在的方式
var?hello2?=?({name})?=>?{console.log("hello,"?+?name)};
//測試
hello2(person);
6. 對象優(yōu)化
新增的API
ES6給Object拓展了許多新的方法,如:
keys(obj):獲取對象的所有key形成的數(shù)組 values(obj):獲取對象的所有value形成的數(shù)組 entries(obj):獲取對象的所有key和value形成的二維數(shù)組。格式: [[k1, v1],[k2, v2],...]assign(dest,...src):將多個src對象的值拷貝到dest中。(第一層為深拷貝,第二層為淺拷貝)
const?person?=?{
??name:?"jack",
??age:?21,
??language:?['java',?'js',?'css']
}
console.log(Object.keys(person));?//["name","age","language"]
console.log(Object.values(person));?//["jack",21,Array(3)]
console.log(Object.entries(person));?//[Array(2),Array(2),Array(2)]
聲明對象簡寫
const?age?=?23
const?name?=?"張三"
//傳統(tǒng)
const?person1?=?{age:?age,?name:?name}
console.log(person1)
//ES6:屬性名和屬性值變量名一樣,可以省略
const?person2?=?{age,?name}
console.log(person2)??//{age:23,name:"張三"}
對象的函數(shù)屬性簡寫
let?person?=?{
??name:?"jack",
??//以前:
??eat:?function(food)?{
????console.log(this.name + "在吃" + food);
??},
??//箭頭函數(shù)版:這里拿不到this
??eat2:?food?=>?console.log(person.name?+?"在吃"?+?food);
??//簡寫版:
??eat3(food)?{
??????console.log(this.name?+?"在吃"?+?food);
??}
}
person.eat("apple");
對象拓展運算符
拓展運算符(...)用于取出參數(shù)對象所有可遍歷屬性然后拷貝到當前對象。
//1、拷貝對象(深拷貝)
let?person1?=?{name:?"Amy",?age:?15}
let?someone?=?{...person1}
console.log(someone)//{name:?"Amy",?age:?15}
//2、合并對象
let?age?=?{age:?15}
let?name?=?{name:?"Amy"}
let?person2?=?{...age,?...name}?//如果兩個對象的字段名重復,后面對象字段值會覆蓋前面對象的字段值
console.log(person2)?//{age:?15,?name:?"Amy"}
7. map和reduce
數(shù)組中新增了map和reduce方法。
map
map():接收一個函數(shù),將原數(shù)組中的所有元素用這個函數(shù)處理后放入新數(shù)組返回。
let?arr?=?['1',?'20',?'-5',?'3'];
console.log(arr)
arr?=?arr.map(s?=>?parseInt(s));
console.log(arr)
reduce
語法:arr.reduce(callback,[initialValue])
reduce為數(shù)組中的每一個元素依次執(zhí)行回調函數(shù),不包括數(shù)組中被刪除或從未被賦值的元素,接受四個參數(shù):初始值(或者上一次回調函數(shù)的返回值),當前元素值,當前索引,調用reduce的數(shù)組。
callback(執(zhí)行數(shù)組中每個值的函數(shù),包含四個參數(shù))
previousValue(上一次調用回調返回的值,或者是提供的初始值(initialValue)) currentValue(數(shù)組中當前被處理的元素) index(當前元素在數(shù)組中的索引) array(調用reduce的數(shù)組)
initialValue(作為第一次調用callback的第一個參數(shù)。) 示例:
const?arr?=?[1,?20,?-5,?3];
//沒有初始值:
console.log(arr.reduce((a,?b)?=>?a?+?b));?//19
console.log(arr.reduce((a,?b)?=>?a?*?b));?//-300
//指定初始值:
console.log(arr.reduce((a,?b)?=>?a?+?b,?1));?//20
console.log(arr.reduce((a,?b)?=>?a?*?b,?0));?//-0
8. Promise
在JavaScript的世界中,所有代碼都是單線程執(zhí)行的。由于這個“缺陷”,導致JavaScript的所有網(wǎng)絡操作,瀏覽器事件,都必須是異步執(zhí)行。異步執(zhí)行可以用回調函數(shù)實現(xiàn)。一旦有一連串的ajax請求a,b,c,d...后面的請求依賴前面的請求結果,就需要層層嵌套。這種縮進和層層嵌套的方式,非常容易造成上下文代碼混亂,我們不得不非常小心翼翼處理內層函數(shù)與外層函數(shù)的數(shù)據(jù),一旦內層函數(shù)使用了上層函數(shù)的變量,這種混亂程度就會加劇......總之,這
種層疊上下文的層層嵌套方式,著實增加了神經(jīng)的緊張程度。
案例:用戶登錄,并展示該用戶的各科成績。在頁面發(fā)送兩次請求:
查詢用戶,查詢成功說明可以登錄 查詢用戶成功,查詢科目 根據(jù)科目的查詢結果,獲取去成績
分析:此時后臺應該提供三個接口,一個提供用戶查詢接口,一個提供科目的接口,一個提供各科成績的接口,為了渲染方便,最好響應json數(shù)據(jù)。在這里就不編寫后臺接口了,而是提供三個json文件,直接提供json數(shù)據(jù),模擬后臺接口:
user.json:
{
??"id":?1,
??"name":?"zhangsan",
??"password":?"123456"
}
user_corse_1.json:
{
??"id":?10,
??"name":?"chinese"
}
corse_score_10.json:
{
??"id":?100,
??"score":?90
}
//回調函數(shù)嵌套的噩夢:層層嵌套。
$.ajax({
????url:?"mock/user.json",
????success(data)?{
????????console.log("查詢用戶:",?data);
????????$.ajax({
????????????url:`mock/user_corse_${data.id}.json`,
????????????success(data){
?????????????console.log("查詢到課程:",?data);
????????????????$.ajax({
????????????????????url:`mock/corse_score_${data.id}.json`,
????????????????????success(data)?{
????????????????????????console.log("查詢到分數(shù):",?data);
????????????????????},
????????????????????error(error)?{
?????????????????????console.log("出現(xiàn)異常了:"?+?error);
????????????????????}
????????????????});
????????????},
????????????error(error){
?????????????console.log("出現(xiàn)異常了:"?+?error);
????????????}
????????});
????},
????error(error){
????????console.log("出現(xiàn)異常了:"?+?error);
????}
});
我們可以通過Promise解決以上問題。
Promise語法
const?promise?=?new?Promise(function(resolve,?reject)?{
?//執(zhí)行異步操作
????if(/*異步操作成功*/)?{
????????resolve(value);?//調用resolve,代表Promise將返回成功的結果
????}?else?{
?????reject(error);//調用reject,代表Promise會返回失敗結果
????}
});
//使用箭頭函數(shù)可以簡寫為:
const?promise?=?new?Promise((resolve,?reject)?=>?{
????//執(zhí)行異步操作
????if(/*異步操作成功*/)?{
????????resolve(value);//調用resolve,代表Promise將返回成功的結果
????}?else?{
????????reject(error);//調用reject,代表Promise會返回失敗結果
????}
});
這樣,在promise中就封裝了一段異步執(zhí)行的結果。
處理異步結果
如果我們想要等待異步執(zhí)行完成,做一些事情,我們可以通過promise的then方法來實現(xiàn)。如果想要處理promise異步執(zhí)行失敗的事件,還可以跟上catch:
promise.then(function(value){
????//異步執(zhí)行成功后的回調
}).catch(function(error){
????//異步執(zhí)行失敗后的回調
})
Promise改造以前嵌套方式
new?Promise((resolve,?reject)?=>?{
????$.ajax({
????????url:"mock/user.json",
????????success(data){
????????????console.log("查詢用戶:",?data);
????????????resolve(data.id);
????????},
????????error(error)?{
????????????console.log("出現(xiàn)異常了:"?+?error);
????????}
????});
}).then((userId)?=>?{
????return?new?Promise((resolve,?reject)?=>?{
????????$.ajax({
????????????url:`mock/user_corse_${userId}.json`,
????????????success(data)?{
????????????????console.log("查詢到課程:", data);
????????????????resolve(data.id);
????????????},
????????????error(error)?{
????????????????console.log("出現(xiàn)異常了:" + error);
????????????}
????????});
????});
}).then((corseId)?=>?{
????console.log(corseId);
????$.ajax({
????????url:?`mock/corse_score_${corseId}.json`,
????????success(data)?{
????????????console.log("查詢到分數(shù):",?data);
????????},
????????error(error)?{
????????????console.log("出現(xiàn)異常了:" + error);
????????}
????});
});
優(yōu)化處理
優(yōu)化:通常在企業(yè)開發(fā)中,會把promise封裝成通用方法,如下:封裝了一個通用的get請求方法;
let?get?=?function(url,?data)?{?//實際開發(fā)中會單獨放到common.js中
????return?new?Promise((resolve,?reject)?=>?{
????????$.ajax({
????????????url:url,
????????????type:"GET",
????????????data:data,
????????????success(result)?{
????????????????resolve(result);
????????????},
????????????error(error)?{
????????????????reject(error);
????????????}
????????});
????})
}
//使用封裝的get方法,實現(xiàn)查詢分數(shù)
get("mock/user.json").then((result)?=>?{
????console.log("查詢用戶:",?result);
????return?get(mock/user_corse_${result.id}.json);?
}).then((result)?=>?{
????console.log("查詢到課程:", result);
????return?get(mock/corse_score_${result.id}.json)
}).catch(()?=>?{
????console.log("出現(xiàn)異常了:"?+?error);
});
通過比較,我們知道了Promise的扁平化設計理念,也領略了這種上層設計帶來的好處。
我們的項目中會使用到這種異步處理的方式;
9. 模塊化
模塊化就是把代碼進行拆分,方便重復利用。類似java中的導包:要使用一個包,必須先導包。而JS中沒有包的概念,換來的是模塊。
模塊功能主要由兩個命令構成:export和import。
export命令用于規(guī)定模塊的對外接口。import命令用于導入其他模塊提供的功能。
export
比如我定義一個js文件:hello.js,里面有一個對象
const?util?=?{
????sum(a,?b)?{
????return?a?+?b;
????}
}
我可以使用export將這個對象導出:
const?util?=?{
????sum(a,?b)?{
????????return?a?+?b;
????}
}
export?{util};
當然,也可以簡寫為:
export?const?util?=?{
????sum(a,?b)?{
????return?a?+?b;
????}
}
export不僅可以導出對象,一切JS變量都可以導出。比如:基本類型變量、函數(shù)、數(shù)組、對象。
當要導出多個值時,還可以簡寫。比如我有一個文件:user.js:
省略名稱
上面的導出代碼中,都明確指定了導出的變量名,這樣其它人在導入使用時就必須準確寫出變量名,否則就會出錯。
因此js提供了default關鍵字,可以對導出的變量名進行省略
例如:
//無需聲明對象的名字
export?default?{
????sum(a,?b)?{
????return?a?+?b;
????}
}
這樣,當使用者導入時,可以任意起名字
import
使用export命令定義了模塊的對外接口以后,其他JS文件就可以通過import命令加載這個模塊。
例如我要使用上面導出的util:
//導入util
import?util?from?'hello.js'
//調用util中的屬性
util.sum(1,?2)
要批量導入前面導出的name和age:
import?{name,?age}?from?'user.js'
console.log(name?+?",?今年"?+?age?+?"歲了")
但是上面的代碼暫時無法測試,因為瀏覽器目前還不支持ES6的導入和導出功能。除非借助于工具,把ES6的語法進行編譯降級到ES5,比如Babel-cli工具
文章已上傳gitee https://gitee.com/codingce/hexo-blog
項目地址github: https://github.com/xzMhehe/codingce-java
? 更多推薦內容 ↓↓↓
以上,便是今天的分享,希望大家喜歡,覺得內容不錯的,歡迎「分享」「贊」或者點擊「在看」支持,謝謝各位。
