ECMAScript 6 簡稱 ES6,是 JavaScript 語言的下一代標準,已經在2015年6月正式發佈了。它的目標是使得 JavaScript 語言能夠用來編寫複雜的大型應用程序,成爲企業級開發語言。前端
ECMAScript 和 JavaScript 的關係:前者是後者的語法規格,後者是前者的一種實現es6
Babel:將ES6代碼轉爲ES5代碼 http://babeljs.io/編程
let 定義的變量不會被變量提高,const 定義的常量不能被修改,let 和 const 都是塊級做用域json
ES6前,js 是沒有塊級做用域 {} 的概念的。(有函數做用域、全局做用域、eval做用域)api
ES6後,let 和 const 的出現,js 也有了塊級做用域的概念,前端的知識是突飛猛進的~數組
變量提高:在ES6之前,var關鍵字聲明變量。不管聲明在何處,都會被視爲聲明在函數的最頂部;不在函數內即在全局做用域的最頂部。這樣就會引發一些誤解。例如:babel
1
2
3
4
5
6
7
8
9
10
11
|
console.log(a);
// undefined
var a =
'hello';
# 上面的代碼至關於
var a;
console.log(a);
a =
'hello';
# 而
let 就不會被變量提高
console.log(a);
// a is not defined
let a =
'hello';
|
const 定義的常量不能被修改異步
1
2
3
4
5
6
7
8
|
var
name =
"bai";
name =
"ming";
console.
log(
name);
// ming
const
name =
"bai";
name =
"ming";
// Assignment to constant variable.
console.
log(
name);
|
import導入模塊、export導出模塊異步編程
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
// 所有導入
import people
from
'./example'
// 將整個模塊看成單一對象進行導入,該模塊的全部導出都會做爲對象的屬性存在
import *
as example
from
"./example.js"
console.log(example.name)
console.log(example.getName())
// 導入部分,引入非 default 時,使用花括號
import {name, age}
from
'./example'
// 導出默認, 有且只有一個默認
export
default App
// 部分導出
export
class App extend Component {};
|
ES5中最使人頭疼的的幾個部分:原型、構造函數,繼承,有了ES6咱們再也不煩惱!函數
ES6引入了Class(類)這個概念。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
class Animal {
constructor() {
this.
type =
'animal';
}
says(say) {
console.log(
this.
type + ' says ' + say);
}
}
let animal =
new
Animal();
animal.says(
'hello');
//animal says hello
class Cat extends Animal {
constructor() {
super();
this.
type =
'cat';
}
}
let cat =
new
Cat();
cat.says(
'hello');
//cat says hello
|
上面代碼首先用class定義了一個「類」,能夠看到裏面有一個constructor方法,這就是構造方法,而this關鍵字則表明實例對象。簡單地說,constructor內定義的方法和屬性是實例對象本身的,而constructor外定義的方法和屬性則是全部實力對象能夠共享的。
Class之間能夠經過extends關鍵字實現繼承,這比ES5的經過修改原型鏈實現繼承,要清晰和方便不少。上面定義了一個Cat類,該類經過extends關鍵字,繼承了Animal類的全部屬性和方法。
super關鍵字,它指代父類的實例(即父類的this對象)。子類必須在constructor方法中調用super方法,不然新建實例時會報錯。這是由於子類沒有本身的this對象,而是繼承父類的this對象,而後對其進行加工。若是不調用super方法,子類就得不到this對象。
ES6的繼承機制,實質是先創造父類的實例對象this(因此必須先調用super方法),而後再用子類的構造函數修改this。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
// ES5
var Shape =
function(id, x, y) {
this.id = id,
this.move(x, y);
};
Shape.prototype.move =
function(x, y) {
this.x = x;
this.y = y;
};
var Rectangle =
function id(ix, x, y, width, height) {
Shape.call(
this, id, x, y);
this.width = width;
this.height = height;
};
Rectangle.prototype =
Object.create(Shape.prototype);
Rectangle.prototype.constructor = Rectangle;
var Circle =
function(id, x, y, radius) {
Shape.call(
this, id, x, y);
this.radius = radius;
};
Circle.prototype =
Object.create(Shape.prototype);
Circle.prototype.constructor = Circle;
// ES6
class Shape {
constructor(id, x, y) {
this.id = id
this.move(x, y);
}
move(x, y) {
this.x = x
this.y = y;
}
}
class Rectangle extends Shape {
constructor(id, x, y, width, height) {
super(id, x, y)
this.width = width
this.height = height;
}
}
class Circle extends Shape {
constructor(id, x, y, radius) {
super(id, x, y)
this.radius = radius;
}
}
|
函數的快捷寫法。不須要 function 關鍵字來建立函數,省略 return 關鍵字,繼承當前上下文的 this 關鍵字
1
2
3
4
5
6
7
8
9
10
11
|
// ES5
var arr1 = [
1,
2,
3];
var newArr1 = arr1.map(
function(x) {
return x +
1;
});
// ES6
let arr2 = [
1,
2,
3];
let newArr2 = arr2.map(
(x) => {
x +
1
});
|
箭頭函數小細節:當你的函數有且僅有一個參數的時候,是能夠省略掉括號的;當你函數中有且僅有一個表達式的時候能夠省略{}
1
2
|
let
arr2 = [
1,
2,
3];
let
newArr2 = arr2.
map(
x => x +
1);
|
JavaScript語言的this對象一直是一個使人頭痛的問題,運行上面的代碼會報錯,這是由於setTimeout中的this指向的是全局對象。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
class Animal {
constructor() {
this.type =
'animal';
}
says(say) {
setTimeout(
function() {
console.log(
this.type +
' says ' + say);
},
1000);
}
}
var animal =
new Animal();
animal.says(
'hi');
//undefined says hi
|
解決辦法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
// 傳統方法1: 將this傳給self,再用self來指代this
says(say) {
var self =
this;
setTimeout(
function() {
console.log(self.type +
' says ' + say);
},
1000);
}
// 傳統方法2: 用bind(this),即
says(say) {
setTimeout(
function() {
console.log(
this.type +
' says ' + say);
}.bind(
this),
1000);
}
// ES6: 箭頭函數
// 當咱們使用箭頭函數時,函數體內的this對象,就是定義時所在的對象
says(say) {
setTimeout(
() => {
console.log(
this.type +
' says ' + say);
},
1000);
}
|
解決了 ES5 在字符串功能上的痛點。
第一個用途:字符串拼接。將表達式嵌入字符串中進行拼接,用 ` 和
${}`來界定。
1
2
3
4
5
6
7
|
// es5
var name1 =
"bai";
console.log(
'hello' + name1);
// es6
const name2 =
"ming";
console.log(
`hello${name2}`);
|
第二個用途:在ES5時咱們經過反斜槓來作多行字符串拼接。ES6反引號 `` 直接搞定。
1
2
3
4
5
6
7
8
|
// es5
var msg =
"Hi \
man!";
// es6
const template = `
<div>
<span>hello world
</span>
</div>`;
|
另外:includes
repeat
1
2
3
4
5
6
7
|
// includes:判斷是否包含而後直接返回布爾值
let str =
'hahah';
console.log(str.includes(
'y'));
// false
// repeat: 獲取字符串重複n次
let s =
'he';
console.log(s.repeat(
3));
// 'hehehe'
|
簡化數組和對象中信息的提取。
ES6前,咱們一個一個獲取對象信息;
ES6後,解構能讓咱們從對象或者數組裏取出數據存爲變量
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
// ES5
var people1 = {
name:
'bai',
age:
20,
color: [
'red',
'blue']
};
var myName = people1.name;
var myAge = people1.age;
var myColor = people1.color[
0];
console.log(myName +
'----' + myAge +
'----' + myColor);
// ES6
let people2 = {
name:
'ming',
age:
20,
color: [
'red',
'blue']
}
let { name, age } = people2;
let [first, second] = people2.color;
console.log(
`${name}----${age}----${first}`);
|
1
2
3
4
5
6
7
8
9
10
|
// ES5 給函數定義參數默認值
function foo(num) {
num = num ||
200;
return num;
}
// ES6
function foo(num = 200) {
return num;
}
|
解決了 es5 複雜的 arguments
問題
1
2
3
4
|
function foo(x, y, ...rest) {
return ((x + y) * rest.length);
}
foo(
1,
2,
'hello',
true,
7);
// 9
|
第一個用途:組裝數組
1
2
3
|
let color = [
'red',
'yellow'];
let colorful = [...color,
'green',
'blue'];
console.log(colorful); // [
"red",
"yellow",
"green",
"blue"]
|
第二個用途:獲取數組除了某幾項的其餘項
1
2
3
|
let
num = [
1,
3,
5,
7,
9];
let [
first,
second, ...
rest] =
num;
console.
log(
rest); // [
5,
7,
9]
|
對象初始化簡寫
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
// ES5
function people(
name, age) {
return {
name:
name,
age: age
};
}
// ES6
function people(
name, age) {
return {
name,
age
};
}
|
對象字面量簡寫(省略冒號與 function 關鍵字)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
// ES5
var people1 = {
name:
'bai',
getName:
function () {
console.log(
this.name);
}
};
// ES6
let people2 = {
name:
'bai',
getName () {
console.log(
this.name);
}
};
|
另外:Object.assign()
ES6 對象提供了Object.assign()這個方法來實現淺複製。Object.assign()能夠把任意多個源對象自身可枚舉的屬性拷貝給目標對象,而後返回目標對象。第一參數即爲目標對象。在實際項目中,咱們爲了避免改變源對象。通常會把目標對象傳爲{}
1
2
3
4
|
const obj =
Object.assign({}, objA, objB)
// 給對象添加屬性
this.seller =
Object.assign({},
this.seller, response.data)
|
用同步的方式去寫異步代碼
1
2
3
4
5
6
7
8
9
|
// 發起異步請求
fetch(
'/api/todos')
.then(
res => res.json())
.then(
data => ({
data
}))
.catch(
err => ({
err
}));
|
生成器( generator)是能返回一個迭代器的函數。
生成器函數也是一種函數,最直觀的表現就是比普通的function多了個星號*
,在其函數體內可使用yield
關鍵字,有意思的是函數會在每一個yield
後暫停。
這裏生活中有一個比較形象的例子。我們到銀行辦理業務時候都得向大廳的機器取一張排隊號。你拿到你的排隊號,機器並不會自動爲你再出下一張票。也就是說取票機「暫停」住了,直到下一我的再次喚起纔會繼續吐票。
迭代器:當你調用一個generator時,它將返回一個迭代器對象。這個迭代器對象擁有一個叫作next的方法來幫助你重啓generator函數並獲得下一個值。next方法不只返回值,它返回的對象具備兩個屬性:done和value。value是你得到的值,done用來代表你的generator是否已經中止提供值。繼續用剛剛取票的例子,每張排隊號就是這裏的value,打印票的紙是否用完就這是這裏的done。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
// 生成器
function *createIterator() {
yield
1;
yield
2;
yield
3;
}
// 生成器能像正規函數那樣被調用,但會返回一個迭代器
let iterator = createIterator();
console.log(iterator.next().value);
// 1
console.log(iterator.next().value);
// 2
console.log(iterator.next().value);
// 3
|
迭代器對異步編程做用很大,異步調用對於咱們來講是很困難的事,咱們的函數並不會等待異步調用完再執行,你可能會想到用回調函數,(固然還有其餘方案好比Promise好比Async/await)。
生成器可讓咱們的代碼進行等待。就不用嵌套的回調函數。使用generator能夠確保當異步調用在咱們的generator函數運行一下行代碼以前完成時暫停函數的執行。
那麼問題來了,我們也不能手動一直調用next()方法,你須要一個可以調用生成器並啓動迭代器的方法。就像這樣子的:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
function run(taskDef) {
// taskDef 即一個生成器函數
// 建立迭代器,讓它在別處可用
let
task = taskDef();
// 啓動任務
let result =
task.
next();
// 遞歸使用函數來保持對 next() 的調用
function
step() {
// 若是還有更多要作的
if (!result.done) {
result =
task.
next();
step();
}
}
// 開始處理過程
step();
}
|
以上就是 ES6 最經常使用的一些語法,能夠說這20%的語法,在ES6的平常使用中佔了80%