最近學(xué)習(xí)了ES6做裙,被它更簡潔的代碼編寫方式、面向?qū)ο笠约澳K化開發(fā)所吸引。ES6有一定的學(xué)習(xí)成本而且知識(shí)點(diǎn)比較瑣碎涌韩,我把自己經(jīng)常用到的知識(shí)點(diǎn)進(jìn)行了整理。
安裝與配置
es6很強(qiáng)大氯夷,遺憾的是所有瀏覽器都沒有完美支持它臣樱。因此我們需要通過babel將es6轉(zhuǎn)換成es5讓我們的代碼在瀏覽器端運(yùn)行。
我本人用的是webpack+babel,你也可以使用gulp或者直接將babel的browser.js引入雇毫,將type設(shè)為"text/babel"玄捕。
首先安裝webpack
npm install webpack --save-dev
webpack需要安裝相應(yīng)的loader加載器—babel-loader,別忘了安裝轉(zhuǎn)換規(guī)則—babel-preset-es2015
npm install babel-loader --save-dev
npm install babel-preset-es2015 --save-dev
接下來簡單地配置一下webpack.config.js文件
module.exports = {
entry: "./main.js",
output: {
path: __dirname,
filename: "after.js"
},
module: {
loaders: [
{
test: /\.js$/,
loader: 'babel-loader',
query: {
presets: ['es2015']
}
}
]
},
}
上面的main.js就是我們即將要寫的es6代碼棚放,通過在命令行輸入webpack
將其轉(zhuǎn)化成es5并保存在after.js中枚粘,因此我們只需要引入after.js即可。如果你希望webpack可以實(shí)時(shí)監(jiān)聽并編譯飘蚯,可以安裝webpack-dev-server馍迄,這里不多說明。
小貼士:如果你在使用es6中的Generator局骤、async的時(shí)候遇到了錯(cuò)誤信息regeneratorRuntime is not defined
攀圈,請(qǐng)單獨(dú)安裝babel-polyfill:在webpack.config.js的頭部var babelpolyfill = require("babel-polyfill");
,將入口文件改寫成entry:["babel-polyfill","./main.js"],
峦甩,然后在你的js中import "babel-polyfill"
赘来。
準(zhǔn)備工作已經(jīng)完成,接下來我們可以測(cè)試一下凯傲,我準(zhǔn)備了一個(gè)用es6編寫的main.js文件
class MyClass{
constructor(x,y){
this.x=x;
this.y=y;
}
print(){
return `(${this.x},${this.y})`;
}
}
var myclass=new MyClass(2,3);
console.log(myclass.print());
運(yùn)行webpack后看看生成的after.js里面都有啥
//部分代碼
var MyClass = function () {
function MyClass(x, y) {
_classCallCheck(this, MyClass);
this.x = x;
this.y = y;
}
_createClass(MyClass, [{
key: "print",
value: function print() {
return "(" + this.x + "," + this.y + ")";
}
}]);
return MyClass;
}();
var myclass = new MyClass(2, 3);
console.log(myclass.print());
可以看到webpack已經(jīng)將es6轉(zhuǎn)化為es5犬辰,現(xiàn)在可以盡情使用es6了。
let和const
let
let是新的變量聲明方式泣洞,使用方法類似于var忧风,但是let聲明的變量只在它所在的代碼塊內(nèi)有效
{
var name="SunnyChuan";
let age=22;
}
console.log(name); //"SunnyChuan"
console.log(age); //age is not defined
let變量只在自己的塊級(jí)作用域內(nèi)有效,也就意味著使用let可以代替閉包解決常見的for循環(huán)引用同一個(gè)變量的問題
for(let i=0;i<5;i++)console.log(i); //0 1 2 3 4
let不存在變量聲明提升球凰,必須先聲明后使用
console.log(name); //ReferenceError
let name="SunnyChuan";
let不允許在同一個(gè)作用域內(nèi)重復(fù)聲明同一個(gè)變量(無論新變量是let/const/var)
let name="SunnyChuan";
var name="DannyQin"; //報(bào)錯(cuò)
const
const是es6增加的另一個(gè)變量聲明方式狮腿,它用來聲明常量,并且聲明后變量的值不能再更改呕诉。因此一旦聲明必須初始化缘厢,不能稍后再賦值
const a=100;
a=10; //TypeError
const b //SyntaxError;
b=100;
const和let一樣存在自己的作用域,個(gè)人認(rèn)為除了變量的值是否可以改變以及是否必須聲明立即初始化之外甩挫,let和const沒有其他區(qū)別贴硫。需要注意的是,對(duì)于對(duì)象伊者,數(shù)組等復(fù)合型的變量英遭,const保證的是地址不變而不是值不變
const arr=[1,2,3];
arr.push(4); //地址不變,改變值是可以的
arr=[5]; //修改了地址亦渗,報(bào)錯(cuò)
變量的解構(gòu)賦值
es6支持解構(gòu)賦值的形式將變量的賦值簡單化挖诸,數(shù)組/對(duì)象/字符串/數(shù)值/布爾/函數(shù)均可解構(gòu)賦值。最為常用的是數(shù)組和對(duì)象法精。
數(shù)組的解構(gòu)賦值
只要等號(hào)兩邊的模式相同即可解構(gòu)成功
var [a,b,c]=[1,2,3] //a=1,b=2,c=3
var [a,,b] //a=1,b=3
var [a,..b] //a=1,b=[2,3]
當(dāng)左邊的數(shù)量大于右邊時(shí)多律,右邊會(huì)默認(rèn)用undefined進(jìn)行補(bǔ)充痴突,導(dǎo)致解構(gòu)不成功
let [a,b,c]=[1,2] //a=1,b=2,c=undefined
允許指定默認(rèn)值,默認(rèn)值只有當(dāng)左邊的變量所對(duì)應(yīng)的右邊的值嚴(yán)格等于undefined才生效
var [a,b,c=3]=[1,2]; //a=1,b=2,c=3
var [a,b,c=3]=[1,2,null]; //a=1,b=2,c=null
對(duì)象的解構(gòu)賦值
與數(shù)組不同的是狼荞,對(duì)象解構(gòu)賦值依靠的是key值辽装,因此只要左邊和右邊key值同名即可(變量名等于屬性名),無所謂順序相味,而數(shù)組是按照順序賦值的
var {name,age}={name:"SunnyChuan",age:22}; //name="SunnyChuan" age=22
//相當(dāng)于
var {name:name,age:age}={name:"SunnyChuan",age:22};
按照上面的匹配方式拾积,變量名必須等于屬性名,如果不相等則匹配失敗攻走。如果變量名不等于屬性名殷勘,只能使用屬性名:變量名的形式,不能省去變量名昔搂。這時(shí)候玲销,屬性只不過是一個(gè)模式,真正被賦值的是變量
var {name:myName,age:myAge}={name:"SunnyChuan",age:22};
//name is not defined, age is not defined, myName="SunnyChuan", myAge=22
對(duì)象解構(gòu)賦值也提供了默認(rèn)值摘符,與數(shù)組相同贤斜,只有屬性值嚴(yán)格等于undefined時(shí)才生效
var {name,age=22}={name:"SunnyChuan"} //name="SunnyChuan" age=22
var {name,age=22}={name:"SunnyChuan",age:null} //name="SunnyChuan" age=null
解構(gòu)賦值最常用的地方就是交換變量。不需要額外的臨時(shí)變量temp逛裤,一句代碼就搞定
[x,y]=[y,x]
字符串/數(shù)值/數(shù)組的擴(kuò)展
字符串的擴(kuò)展
includes(str)瘩绒,返回布爾值,是否在當(dāng)前字符串中找到了str
"SunnyChuan".includes("Chuan"); //true
startsWith(str)带族,返回布爾值锁荔,當(dāng)前字符串是否以str開頭
"SunnyChuan".startsWidth("Sunny"); //true
endsWith(str),返回布爾值蝙砌,當(dāng)前字符串是否以str結(jié)尾
"SunnyChuan".endsWith("Chuan"); //true
repeat(n)阳堕,將當(dāng)前字符串重復(fù)n次(可以理解為在原有的基礎(chǔ)上重復(fù)n-1次)并返回新字符串,如果n是小數(shù)則向下取整择克。當(dāng)n小于等于0時(shí)恬总,返回空字符串
"x".repeat(3); // "xxx"
模板字符串
var name="SunnyChuan";
var str=`hello ${name},this is ES6 `;
//等同于"hello"+name+",this is ES6";
數(shù)值的擴(kuò)展
Number.isFinite(n),布爾值肚邢,檢查n是否有窮壹堰,與es5的isFinite()不同的是,它不會(huì)進(jìn)行類型轉(zhuǎn)換骡湖,因此只對(duì)真正的數(shù)值有效
Number.isFinite(10); //true
Number.isFinite(NaN); //false
Number.isFinite(Infinity); //false
Number.isFinite("10"); //false
Number.isNaN(n)贱纠,布爾值,檢查n是否是NaN响蕴,與es5的isNaN()不同的是并巍,它不會(huì)進(jìn)行類型轉(zhuǎn)換,因此只對(duì)真正的NaN有效
Number.isNaN(NaN); //true
Number.isNaN("str"); //false
Number.isInteger(n)换途,布爾值懊渡,檢查n是否是整數(shù),需要注意1.0和1是同一個(gè)值
Number.isInteger(1); //true
Number.isInteger(1.0); //true
Number.isInteger(1.2); //false
Math.trunc(n)军拟,去除小數(shù)部分并返回(正數(shù)向下取整剃执,負(fù)數(shù)向上取整)
Math.trunc(1.2); //1
Math.trunc(-1.2); //-2
Math.sign(n),布爾值懈息,n是正數(shù)返回+1肾档,是負(fù)數(shù)返回-1,0返回0辫继,-0返回-0怒见,其他值返回NaN
Math.sign(100); //+1
Math.sign(-100); //-1
Math.sign(0); //0
Math.sign(-0); //-0
Math.sign("str"); //NaN
數(shù)組的擴(kuò)展
Array.from(list),將list轉(zhuǎn)化成真正的數(shù)組姑宽,常用于將nodeList/arguments等偽數(shù)組
轉(zhuǎn)化成數(shù)組
var obj={a:1,b:2,c:3};
Array.from(obj); //[1,2,3]
var div=document.getElementsByTagName("div");
Array.from(div); //[[object HTMLDivElement],[object HTMLDivElement],[object HTMLDivElement]]
includes(n)遣耍,布爾值,檢查當(dāng)前數(shù)組是否包含n炮车,可以接收兩個(gè)參數(shù)舵变,第二個(gè)參數(shù)代表搜索的起始位置(負(fù)數(shù)代表從后往前)
[1,2,3,4].include(2); //true
[1,2,3,4].include(2,2); //false
[1,2,3,4].include(2,-3); //true
數(shù)組新增三種遍歷方式:entries()(遍歷key和value)/keys()(遍歷key)/values()(遍歷value)
for(let v of ["a","b","c","d"].values()){
console.log(v);
} //"a" "b" "c" "d"
for(let k of ["a","b","c","d"].keys()){
console.log(k);
} //0 1 2 3
for(let [k,v] of ["a","b","c","d"].entries()){
console.log(k,v);
} //0 "a" 1 "b" 2 "c" 3 "d"
函數(shù)和對(duì)象的擴(kuò)展
函數(shù)的擴(kuò)展
es6支持函數(shù)的參數(shù)設(shè)置默認(rèn)值,但是這些參數(shù)必須位于函數(shù)的尾部瘦穆,并且參數(shù)的變量是默認(rèn)聲明的纪隙,因此不能用let/const再次聲明
function func(x,y=5){
console.log(y); //5
let y=3; //error
}
擴(kuò)展運(yùn)算符,用于將數(shù)組(偽數(shù)組)展開成參數(shù)序列
console.log(...[1,2,3]); //1 2 3
[...document.getElementsByTagName("div")]; //[[object HTMLDivElement],[object HTMLDivElement],[object HTMLDivElement]]
擴(kuò)展運(yùn)算符有很多應(yīng)用場(chǎng)景扛或,這里列舉三個(gè)
- 數(shù)組合并
[1,2,3].concat([4,5,6]); //es5
[1,2,3,...[4,5,6]]; //es6
2.與解構(gòu)結(jié)合(用于生成數(shù)組)
let [a,b,...c]=[1,2,3,4,5]; //a=1,b=2,c=[3,4,5] 擴(kuò)展運(yùn)算符必須放在最后
3.Math.max的參數(shù)不支持?jǐn)?shù)組绵咱,在es5中需要用到apply。用擴(kuò)展運(yùn)算符可以解決該問題
Math.max.apply(Math,[1,2,3]); //es5
Math.max(...[1,2,3]); //es6 相當(dāng)于Math.max(1,2,3)
箭頭函數(shù)熙兔,如果不需要參數(shù)則用圓括號(hào)代替參數(shù)部分悲伶,如果函數(shù)體有多行代碼則用大括號(hào)括起來
var func=x=>x*2; //var func=function(x){return x*2;}
var func=()=>true; //var func=function(){return true;}
var func=(x,y)=>{var z=x+y;console.log(z);} //var func=function(x,y){var z=x+y;console.log(z);}
var func=()=>({a:1,b:2}); //返回對(duì)象需要用圓括號(hào)包起來,圓括號(hào)代表函數(shù)體黔姜,花括號(hào)代表這是一個(gè)對(duì)象
函數(shù)綁定拢切,使用a::b的形式取代傳統(tǒng)的bind/call/apply
a::b; //b.bind(a);
a::b(...arguments); //b.apply(a,arguments);
對(duì)象的擴(kuò)展
es6允許在對(duì)象中只寫key,這樣默認(rèn)了value等于key所代表的變量值
var [name,age]=["SunnyChuan",22];
var obj={name,age}; //obj={name:"SunnyChuan",age:22}
//相當(dāng)于obj={name:name,age:age};
對(duì)象的方法也可以簡寫
var obj={
func(){
//函數(shù)體
}
}
//相當(dāng)于
var obj={
func:function(){
//函數(shù)體
}
}
Object.assign(obj,obj1,obj2,...)秆吵,將obj1/obj2/...與obj進(jìn)行拼接(修改obj本身)
var [obj,obj1,obj2]=[{a:1},{b:2},{c:3}];
Object.assign(obj,obj1,obj2);
console.log(obj); //{a:1,b:2,c:3}
Object.is(obj1,obj2)淮椰,布爾值,判斷兩個(gè)值是否嚴(yán)格相等纳寂,與===不同的是主穗,+0不等于-0,NaN等于NaN
Object.is(100,100); //true
Object.is(NaN,NaN); //true
Object.is(+0,-0); //false
Object.is({a:1},{a:1}); //false