一、ES6声明变量的6种方法

1、ES5声明变量:

var 和 function 两种方式.
复制代码

2、ES6声明变量:

1、var可以先使用后声明,有变量提升      function 
2、新增:
	(1)、const 声明一个常量(只读),一旦声明,值不能再改变、
	(2)、let 声明的变量是一个块级域,只在本作用域内有效,且必须先声明后使用。(不会有变量提升)
	(3)、import 可以引入外部变量或者文件  
	(4)、import {param1,param2} form "../vue.js" 从vue.js中引入两个变量 或者
	(5)、import App(随意定义变量名,但是尽量和文件名一直,好方便使用vue中) from "../app.vue";
	(6)、class
复制代码

二、块级作用域

1、es5只有全局作用于和函数作用于,没有块级作用域 

2、es6 允许块级作用域的任意嵌套

3、es5规定函数只能在顶层作用域和函数作用域之中声明,

   不能在块级作用域声明,严格模式下会报错。

   为ES5和es6环境避免报错,应不要在块级作用域里声明函数。
复制代码

三、const 命令

1、const声明一个只读的常量。一旦声明,常量的值就不能改变。

2、const的作用域与let命令相同:只在声明所在的块级作用域内有效。

3、const命令声明的常量也是不提升,同样存在暂时性死区,只能在声明的位置后面使用

4、对于复合类型的变量,变量名不指向数据,而是指向数据所在的地址。const命令只是保证变量名指向的地址不变,
  
 并不保证该地址的数据不变,所以将一个对象声明为常量必须非常小心。


const foo = {};  // 为 foo 添加一个属性,可以成功  

foo.prop = 123;  
foo.prop // 123  
   
foo = {}; // TypeError: "foo" is read-only  	// 将 foo 指向另一个对象,就会报错 
复制代码

四、 es6十大特性

1、Default Parameters(默认参数) in ES6
以前不得不通过下面方式来定义默认参数:

var link = function (height, color, url) {
 var height = height || 50;
 var color = color || 'red';
 var url = url || 'http://azat.co';
 ...
}
一切工作都是正常的,直到参数值是0后,就有问题了,因为在JavaScript中,0表示fasly,

它是默认被hard-coded的值,而不能变成参数本身的值。当然,如果你非要用0作为值,

我们可忽略这一缺陷并且使用逻辑OR方可!但在ES6,我们可以直接把默认值放在函数申明里:

var link = function(height = 50, color = 'red', url = 'http://azat.co') {
  ...
}

这个语法类似于Ruby!
复制代码
2、Template Literals (模板文本)in ES6 name is ${变量}
在其它语言中,使用模板和插入值是在字符串里面输出变量的一种方式。因此,在ES5,我们可以这样组合一个字符串:

var name = 'Your name is ' + first + ' ' + last + '.';

var url = 'http://localhost:3000/api/messages/' + id;

幸运的是,在ES6中,我们可以使用新的语法$ {NAME},并把它放在反引号里:

var name = `Your name is ${first} ${last}. `;

var url = `http://localhost:3000/api/messages/${id}`;
复制代码
3、Multi-line Strings (多行字符串)in ES6

1、ES6的多行字符串是一个非常实用的功能。在ES5中,我们不得不使用以下方法来表示多行字符串:

var roadPoem = 'Then took the other, as just as fair,nt'
    + 'And having perhaps the better claimnt'
    + 'Because it was grassy and wanted wear,nt'
    + 'Though as for that the passing therent'
    + 'Had worn them really about the same,nt';
var fourAgreements = 'You have the right to be you.n
You can only be you when you do your best.';
复制代码

2、然而在ES6中,仅仅用反引号就可以解决了:

var roadPoem = `Then took the other, as just as fair,
    And having perhaps the better claim
    Because it was grassy and wanted wear,
    Though as for that the passing there
    Had worn them really about the same,`;
var fourAgreements = `You have the right to be you.
	You can only be you when you do your best.`;
复制代码
4、Destructuring Assignment (解构赋值)in ES6

1、解构可能是一个相对难以掌握的概念。先从一个简单的赋值讲起,其中cat 和 mouse是key,同时cat 和mouse也是一个变量,在ES5中是这样:

var data = $('body').data(), // data has properties cat and mouse
 house = data.cat,
 mouse = data.mouse;
复制代码

2、在node.js中用ES5是这样:

var jsonMiddleware = require('body-parser').jsonMiddleware ;
var body = req.body, // body has username and password
   username = body.username,
   password = body.password;
复制代码

3、在ES6,我们可以使用这些语句代替上面的ES5代码:

var { cat, mouse} = $('body').data(); // we'll get cat and mouse variables
var {jsonMiddleware} = require('body-parser');
var {username, password} = req.body;
复制代码

4、这个同样也适用于数组:

var [col1, col2]  = $('.column'),
   [line1, line2, line3, , line5] = file.split('n');
复制代码
5、Enhanced Object Literals (增强的对象文本)in ES6
6、Arrow Functions (箭头函数)in ES6

在ES6中,也有了丰富的箭头函数,它们将使许多操作变成现实,以前我们使用闭包,this总是预期之外地产生改变,而箭头函数的迷人之处在于,现在你的this可以按照你的预期使用了,

身处箭头函数里面,this还是原来的this。有了箭头函数在ES6中, 我们就不必用that = this或 self = this 或

_this = this 或.bind(this)。

例如,下面的代码用ES5就不是很优雅:

var _this = this;
$('.btn').click(function(event){
  _this.sendData();
})
在ES6中就不需要用 _this = this:

$('.btn').click((event) =>{
  this.sendData();
})
复制代码

2、以前的function的传递方式也是一个很好的方案,ES6委员仍然保留了以前的功能。

下面这是一个另外的例子,我们通过call传递文本给logUpperCase() 函数在ES5中:

var logUpperCase = function() {
  var _this = this;
 
  this.string = this.string.toUpperCase();
  return function () {
    return console.log(_this.string);
  }
}

logUpperCase.call({ string: 'ES6 rocks' })();
复制代码

3、而在ES6,我们并不需要用_this浪费时间:

var logUpperCase = function() {
  this.string = this.string.toUpperCase();
  return () => console.log(this.string);
}
logUpperCase.call({ string: 'ES6 rocks' })();

请注意,只要你愿意,在ES6中=>可以混合和匹配老的函数一起使用。

当在一行代码中用了箭头函数,它就变成了一个表达式。它将暗地里返回单个语句的结果。

如果你超过了一行,将需要明确使用return。
这是用ES5代码创建一个消息数组:

var ids = ['5632953c4e345e145fdf2df8','563295464e345e145fdf2df9'];
var messages = ids.map(function (value) {
  return "ID is " + value; // explicit return
});
复制代码

4、用ES6:

var ids = ['5632953c4e345e145fdf2df8','563295464e345e145fdf2df9'];
var messages = ids.map(value => `ID is ${value}`); // implicit return
复制代码

请注意,这里用了字符串模板。在箭头函数中,对于单个参数,括号()是可选的,但当你超过一个参数的时候你就需要他们。

在ES5代码有明确的返回功能:

var ids = ['5632953c4e345e145fdf2df8', '563295464e345e145fdf2df9'];
var messages = ids.map(function (value, index, list) {
  return 'ID of ' + index + ' element is ' + value + ' '; // explicit return
});
复制代码

在ES6中有更加严谨的版本,参数需要被包含在括号里并且它是隐式的返回:

var ids = ['5632953c4e345e145fdf2df8','563295464e345e145fdf2df9'];

var messages = ids.map((value, index, list) => `ID of ${index} element is ${value} `); 

// implicit return
复制代码
7、Promises in ES6

1、在ES6中有标准的Promise实现。下面是一个简单的用setTimeout()实现的异步延迟加载函数:

setTimeout(function(){
  console.log('Yay!');
}, 1000);
复制代码

2、在ES6中,我们可以用promise重写:

var wait1000 =  new Promise(function(resolve, reject) {
  setTimeout(resolve, 1000);
}).then(function() {
  console.log('Yay!');
});

或者用ES6的箭头函数:

var wait1000 =  new Promise((resolve, reject)=> {
  setTimeout(resolve, 1000);
}).then(()=> {
  console.log('Yay!');
});
复制代码

3、代码的行数从三行增加到五行,并没有任何明显的好处。确实,如果我们有更多的嵌套逻辑在setTimeout()回调函数中,我们将发现更多好处:

setTimeout(function(){
  console.log('Yay!');
  setTimeout(function(){
    console.log('Wheeyee!');
  }, 1000)
}, 1000);
在ES6中我们可以用promises重写:

var wait1000 =  ()=> new Promise((resolve, reject)=> {setTimeout(resolve, 1000)});
wait1000()
    .then(function() {
        console.log('Yay!')
        return wait1000()
    })
    .then(function() {
        console.log('Wheeyee!')
    });
复制代码

还是不确信Promises 比普通回调更好?其实我也不确信,我认为一旦你有回调的想法,那么就没有必要额外增加promises的复杂性。 虽然,ES6 有让人崇拜的Promises 。Promises 是一个有利有弊的回调但是确实是一个好的特性,更多详细的信息关于promise:Introduction to ES6 Promises.

8、Block-Scoped Constructs Let and Const(块作用域构造Let and Const)

1、在ES6代码中,let是更复杂;是一种新的变量申明方式,它允许你把变量作用域控制在块级里面。我们用大括号定义代码块,在ES5中,块级作用域起不了任何作用:

function calculateTotalAmount (vip) {
  var amount = 0;
  if (vip) {
    var amount = 1;
  }
  { // more crazy blocks!
    var amount = 100;
    {
      var amount = 1000;
    }
  }
  return amount;
}
console.log(calculateTotalAmount(true));

结果将返回1000,这真是一个bug。在ES6中,我们用let限制块级作用域。而var是限制函数作用域。

function calculateTotalAmount (vip) {
  var amount = 0; // probably should also be let, but you can mix var and let
  if (vip) {
    let amount = 1; // first amount is still 0
  }
  { // more crazy blocks!
    let amount = 100; // first amount is still 0
    {
      let amount = 1000; // first amount is still 0
    }
  }
  return amount;
}
 
console.log(calculateTotalAmount(true));
复制代码

这个结果将会是0,因为块作用域中有了let。如果(amount=1).那么这个表达式将返回1。

谈到const,就更加容易了;它就是一个不变量,也是块级作用域就像let一样。

下面是一个演示,这里有一堆常量,它们互不影响,因为它们属于不同的块级作用域:

function calculateTotalAmount (vip) {
  const amount = 0;
  if (vip) {
    const amount = 1;
  }
  { // more crazy blocks!
    const amount = 100 ;
    {
      const amount = 1000;
    }
  }
  return amount;
}
console.log(calculateTotalAmount(true));
复制代码

从我个人看来,let 和const使这个语言变复杂了。没有它们的话,我们只需考虑一种方式,现在有许多种场景需要考虑。

9、Classes(类) in ES6

1、在过去的ES5中,因为没有一个关键字class (它被保留,但是什么也不能做)。在此之上,大量的继承模型像pseudo classical, classical,

functional 更加增加了混乱,JavaScript 之间的宗教战争只会更加火上浇油。

用ES5写一个类,有很多种方法,这里就先不说了。现在就来看看如何用ES6写一个类吧。

ES6没有用函数, 而是使用原型实现类。我们创建一个类baseModel ,并且在这个类里定义了一个constructor 和一个 getName()方法:

class baseModel {
  constructor(options, data) { // class constructor,node.js 5.6暂时不支持options = {}, data = []这样传参
    this.name = 'Base';
    this.url = 'http://azat.co/api';
    this.data = data;
    this.options = options;
   }
 
    getName() { // class method
        console.log(`Class name: ${this.name}`);
    }
}
复制代码

注意我们对options 和data使用了默认参数值。此外方法名也不需要加function关键字,而且冒号(:)也不需要了。

另外一个大的区别就是你不需要分配属性this。现在设置一个属性的值,只需简单的在构造函数中分配。

AccountModel 从类baseModel 中继承而来:

class AccountModel extends baseModel {
    constructor(options, data) {
复制代码

为了调用父级构造函数,可以毫不费力的唤起super()用参数传递:

super({private: true}, ['32113123123', '524214691']); //call the parent method with super
       this.name = 'Account Model';
       this.url +='/accounts/';
    }
复制代码

如果你想做些更好玩的,你可以把 accountData 设置成一个属性:

get accountsData() { //calculated attribute getter
    // ... make XHR
        return this.data;
    }
}
复制代码

你如何调用他们呢?它是非常容易的:

let accounts = new AccountModel(5);
accounts.getName();
console.log('Data is %s', accounts.accountsData);
复制代码

结果令人惊讶,输出是:

Class name: Account Model
Data is  32113123123,524214691
复制代码
10、Modules(模块) in ES6

1、在ES6以前JavaScript并不支持本地的模块。人们想出了AMD,RequireJS,CommonJS以及其它解决方法。现在ES6中可以用模块import 和export 操作了。

在ES5中,你可以在