1.塊級做用域變量javascript
使用let/const,而非var來聲明變量。java
var的問題是變量會泄漏到其它代碼塊,好比for循環或是if塊。jquery
2.當即執行函數表達式(IIFE)編程
1 //ES5 2 { 3 4 var private = 1; 5 6 } 7 console.log(private);//1
private會發生泄漏。須要使用當即執行函數表達式將其包起來promise
1 ES5 2 (function(){ 3 var private2=1; 4 })(); 5 console.log(private2);// Uncaught ReferenceError
若是看過jquery或是其它開源項目的代碼,你會注意到它們都利用了當即執行函數表達式,以免污染全局環境,而只在全局下定義_\$或是jQuery。瀏覽器
ES6更工整,再也不須要使用IIFE,只用塊和let就能夠了:服務器
1 //ES6 2 { 3 let private3 = 1; 4 } 5 console.log(private3);//Uncaught ReferenceError
3.Const異步
若是不但願變量的值再改變,可使用const。模塊化
4.類和對象異步編程
在javascript中,每一個對象都有原型對象。全部javascript對象都從原型上繼承方法和屬性。
ES5以面向對象編程的方式建立對象,是利用構造函數實現的:
1 //ES5 2 var Animal = (function(){ 3 function MyConstructor(name){ 4 this.name = name; 5 } 6 MyConstructor.prototype.speak = function speak(){ 7 console.log(this.name+' makes a noise'.); 8 } 9 return MyConstructor; 10 })(); 11 var animal = new Animal('animal); 12 animal.speak();//animal makes a noise.
ES6提供了語法糖,能夠用class、constructor等新的關鍵字、更少的樣板代碼實現相同的效果。
1 ES6 2 class Animal{ 3 constructor(name){ 4 this.name = name; 5 } 6 speak(){ 7 console.log(this.name +'makes a noises.'); 8 } 9 } 10 const animal = new Animal('animal'); 11 animal.speak();//animal makes a noise.
最佳實踐:
最好使用class語法,避免直接操做prototype。緣由是這樣代碼更簡明易懂。
避免出現空的構造器,若是沒有指明,類會有默認的構造器。
5.繼承
ES5
1 //傳統構造函數繼承 2 function Animal() { 3 this.eat = function () { 4 alert('Animal eat') 5 } 6 } 7 function Dog() { 8 this.bark = function () { 9 alert('Dog bark') 10 } 11 } 12 Dog.prototype = new Animal()// 綁定原型,實現繼承 13 var hashiqi = new Dog() 14 hashiqi.bark()//Dog bark 15 hashiqi.eat()//Animal eat
ES6提供了新的關鍵字extends和super
1 //ES6繼承 2 class Animal { 3 constructor(name) { 4 this.name = name 5 } 6 eat() { 7 alert(this.name + ' eat') 8 } 9 } 10 class Dog extends Animal { 11 constructor(name) { 12 super(name) // 有extend就必需要有super,它表明父類的構造函數,即Animal中的constructor 13 this.name = name 14 } 15 say() { 16 alert(this.name + ' say') 17 } 18 } 19 const dog = new Dog('哈士奇') 20 dog.say()//哈士奇 say 21 dog.eat()//哈士奇 eat
效果相同,可是相比於ES5,ES6代碼更易讀,完勝。
6.Promise
Promise是異步編程的一種解決方案,比傳統的解決方案(回調函數和事件)更合理更強大
1 function printAfterTimeout(string, timeout, done){ 2 setTimeout(function(){ 3 done(string); 4 }, timeout); 5 } 6 printAfterTimeout('Hello ', 2e3, function(result){ 7 console.log(result); 8 // nested callback 9 printAfterTimeout(result + 'Reader', 2e3, function(result){ 10 console.log(result); 11 }); 12 });
這個函數接收一個回調,在done後執行。咱們想要前後執行兩次,因此在回調中又一次調用了printAfterTimeout。若是須要3或4次回調,代碼很快就一團糟了。
ES6中的promise很好的解決了回調地獄的問題,所謂的回調地獄是指當太多的異步步驟須要一步一步執行,或者一個函數裏有太多的異步操做,這時候就會產生大量嵌套的回調,使代碼嵌套太深而難以閱讀和維護。ES6認識到了這點問題,如今promise的使用,完美解決了這個問題。
promise 原理:
promise對象初始化狀態爲pending:當調用resolve(成功),會由pending=>fulfilled;
當調用reject(失敗),會由pending=>rejected,具體流程見下圖:
promise的使用流程
1.new Promise一個實例,並且要return
2.new Promise時要傳入函數,函數有resolve reject兩個參數
3.成功時執行resolve,失敗時執行reject
4.then監聽結果
1 function loadImg(src){ 2 const promise=new Promise(function(resolve,reject){ 3 var img=document.createElement('img') 4 img.onload=function(){ 5 resolve(img) 6 } 7 img.onerror=function(){ 8 reject() 9 } 10 img.src=src 11 }) 12 return promise//返回一個promise實例 13 } 14 var src="http://www.imooc.com/static/img/index/logo_new.png" 15 var result=loadImg(src) 16 result.then(function(img){ 17 console.log(img.width)//resolved(成功)時候的回調函數 18 },function(){ 19 console.log(「failed「)//rejected(失敗)時候的回調函數 20 }) 21 result.then(function(img){ 22 console.log(img.height) 23 })
promise 中能夠用 then
在某個函數完成後執行新的代碼,而沒必要再嵌套函數。
7.ES6模塊化
ES6實現了模塊功能,旨在成爲瀏覽器和服務器通用的模塊解決方案。其模塊功能主要由兩個命令構成:export和
import。export命令用於規定模塊的對外接口,import命令用於輸入其它模塊提供的功能。
1 /** 定義模塊 math.js **/ 2 var basicNum = 0; 3 var add = function (a, b) { 4 return a + b; 5 }; 6 export { basicNum, add }; 7 /** 引用模塊 **/ 8 import { basicNum, add } from './math'; 9 function test(ele) { 10 ele.textContent = add(99 + basicNum); 11 }
如上例所示,使用import命令的時候,用戶須要知道所要加載的變量名或函數名,不然沒法加載。爲了給用戶
提供方便,讓他們不用閱讀文檔就能加載模塊,就要用到export default命令,爲模塊制定默認輸出。
1 export default function(){ 2 console.log('foo); 3 }
上面代碼是一個模塊文件export-default.js,它的默認輸出是一個函數。其它模塊加載該模塊時,import命令能夠爲
該匿名函數指定任意名字。
1 import customName from './export-default'; 2 customName();//'foo'
上面代碼的import命令,能夠用任意名稱指向export-default.js輸出的方法,這時就不須要知道原模塊輸出的函數
名。須要注意的是,這時import命令後面,不使用大括號。