一直以來,我對ES6都不甚感興趣,一是由於在生產環境中使用ES5已經是到處碰壁,其次則是隻當這ES6是語法糖未曾重視。
只是最近學習react生態,用起babel來轉換jsx之餘,也難免碰到諸多用上ES6的教程、案例,所以便稍做學習。這一學習,便以爲這語法糖實在是甜,忍不住嚐鮮,因而記錄部分自覺對本身有用的方法在此。javascript
箭頭函數是一個典型的語法糖,即創造了一種新語法來簡化javascript中函數的寫法:java
// ES5 var selected = allJobs.filter(function (job) { return job.isSelected(); }); // ES6 var selected = allJobs.filter(job => job.isSelected());
上面這是函數只有一個形參的狀況,下面列舉函數有多個形參的狀況:react
// ES5 var total = values.reduce(function (a, b) { return a + b; }, 0); // ES6 var total = values.reduce((a, b) => a + b, 0);
語法大致是這樣:([函數的形參,多個參數則以逗號分隔]) => [函數返回的值/表達式]
另外,箭頭函數也可使用{}
來引入函數塊語句,不過這樣的話其實就只是簡寫了function
這一個單詞了,意義不是很大,下面放個例子:編程
// ES5 $("#confetti-btn").click(function (event) { playTrumpet(); fireConfettiCannon(); }); // ES6 $("#confetti-btn").click(event => { playTrumpet(); fireConfettiCannon(); });
對我來講,簡寫並不吸引我,吸引個人,是箭頭函數的一個重要特性:箭頭函數沒有它本身的this值,箭頭函數內的this值繼承自外圍做用域。數組
2016-05-31修改: @n͛i͛g͛h͛t͛i͛r͛e͛
同窗指出babel
arrow function 不是「沒有本身的 this」,而是綁定了定義時的 context;這一特性等價於之前的
Function.prototype.bind
我翻查了一下MDN,裏面是這麼寫的:閉包
箭頭函數則會捕獲其所在上下文的 this 值,做爲本身的 this 值。
所以,@n͛i͛g͛h͛t͛i͛r͛e͛
同窗的說法是有理的。函數式編程
這在編寫回調函數的時候就很是好用了,咱們不再須要利用閉包來保存this了(尤爲是,很容易忘記保存this而直接在回調函數裏用了this):函數
{ add: function(piece) {}, ... addAll: function addAll(pieces) { var self = this; _.each(pieces, function (piece) { self.add(piece); }); }, ... } // ES6 { add: function(piece) {}, ... addAll: function addAll(pieces) { _.each(pieces, piece => this.add(piece)); }, ... }
自ES6中let
的出現,javascript終於迎來了塊級做用域({}、for、if)。學習
2016-05-31修改:
此處表達有誤,應爲:自ES6,javascript開始擁有塊級做用域,而let
則是配合塊級做用域,做爲替代var
的一個語法定義。
有了塊級做用域,不再用擔憂臨時變量污染到外層的變量了:
function f1() { let n = 5; if (true) { let n = 10; } console.log(n); // 5 }
const
是用來定義常量的,一旦定義了就不可修改(一修改就報錯)。用途嘛,也比較單一,就是定義一下配置項什麼的,省得被團隊裏的愣頭青寫的代碼給瞎改了。
2016-05-31修改 @n͛i͛g͛h͛t͛i͛r͛e͛
同窗提出一個「命名綁定」的概念,並舉出一個相應的例子:
const config = {}; config.env = 'development'; // 這不會報錯 config = {}; // 這纔會報錯
請恕我才疏學淺,尚不能理解「命名綁定」呀、函數式編程之類的。我對上面這個例子的理解是,config只是一個object的引用,不管這個object自己怎麼變化,只要config這個變量的「指向」沒變化,那就不會報錯。
destructuring是解構的意思,ES6容許按照必定模式,從數組和對象中提取值,對變量進行賦值,這被稱爲解構(Destructuring)。來兩個例子看看你們就明白了。
'use strict'; // 數組的解構賦值 let [foo, [[bar], baz]] = [1, [[2], 3]]; console.log(foo); // 1 console.log(bar); // 2 console.log(baz); // 3 // 對象的解構賦值 var { foo, bar } = { foo: "aaa", bar: "bbb" }; console.log(foo); // "aaa" console.log(bar ); // "bbb" // 字符串的解構賦值 const [a, b, c, d, e] = 'hello'; console.log(a + b + c + e); // 'hello'
跟箭頭函數同樣,也是個語法糖,那這是用在什麼地方呢?請不要着急,聽我細細道來:
在咱們封裝函數的時候,若是形參較多,爲了使用者不須要按順序來傳入參數,每每用一個object來承載全部的參數,例如這樣:
// 二逼青年寫法 function study(id, name, sex, grade, nickname, age, address) { console.log(id); console.log(name); console.log(sex); console.log(grade); console.log(nickname); console.log(age); console.log(address); } // 正常青年寫法 function study(params) { console.log(params.id); console.log(params.name); console.log(params.sex); console.log(params.grade); console.log(params.nickname); console.log(params.age); console.log(params.address); }
這種作法,雖然說使用者是方便了,但寫函數的人卻麻煩了,每次用參數都要帶上params.
,或者再寫個var id = params.id
來讓後續的使用方便一些。
然而,有了destructuring
後,咱們有了更方便的寫法:
function study({id, name, sex, grade, nickname, age, address}) { console.log(id); console.log(name); console.log(sex); console.log(grade); console.log(nickname); console.log(age); console.log(address); } study({ id: 1, name: '林有德', sex: '男', grade: '一年級', nickname: '布萊德', age: 12, address: '木馬號' });
這樣一來,使用者用起來很方便,而函數內部又直接解構賦值到各變量上,用起來也方便多了。