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命令后面,不使用大括号。