一、简介
ES6, 全称 ECMAScript 6.0 ,是 JavaScript 的下一个版本标准,2015.06 发版。
ES6 主要是为了解决 ES5 的先天不足,比如 JavaScript 里并没有类的概念。
二、ES6 的目标与愿景
成为更好编写的开发语言有以下目标。
适应更复杂的应用;实现代码库之间的共享;不断迭代维护新版本。
三、ES6 环境
目前各大浏览器基本上都支持 ES6 的新特性,其中 Chrome 和 Firefox 浏览器对 ES6 新特性最友好,IE7~11 基本不支持 ES6。
四、ES6基础
4.1 let命令
ES6新增了let命令,用来声明变量。它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效。
1 | if (true) { |
块级作用域在一些情况下,可以避免内层变量覆盖外层变量。
Let不存在变量提升
1 | //var的情况 |
控制台的输出结果:
上面代码中,变量t1用var命令声明,会发生变量提升,即脚本开始运行时,变量t1已经存在了,但是没有值,所以会输出undefined。
变量bar用let命令声明,不会发生变量提升。这表示在声明它之前,变量bar是不存在的,这时如果用到它,就会抛出一个错误。 因此,使用let声明变量,极大的消除了代码的潜在bug的隐患。
Let暂时性死区:
1 | var temp = 123; |
上面代码中,存在全局变量tmp,但是块级作用域内let又声明了一个局部变量tmp,导致后者绑定这个块级作用域,所以在let声明变量前,对tmp赋值会报错。
4.2 const 命令
const声明一个只读的常量。一旦声明,常量的值就不能改变
1 | const PI = 3.1415926; |
上面代码表明改变常量的值会报TypeError: Assignment to constant variable的错。
4.3 模板字符串
1 | <p id="result"></p> |
注意:ES6模板字符串中必须要使用反引号。
4.4 rest参数
ES6 引入 rest 参数(形式为“…变量名”),用于获取函数的多余参数。rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中。
1 | function add(...values) { |
上面代码的add函数是一个求和函数,利用 rest 参数,可以向该函数传入任意数目的参数。rest 参数中的变量代表一个数组,所以数组特有的方法都可以用于这个变量。
4.5 箭头函数
ES6允许使用“箭头”(=>)定义函数:
如果箭头函数不需要参数或需要多个参数,就使用一个圆括号代表参数部分
1 | // 1. 不需要参数 |
如果只有一个参数,那么圆括号就可以省略了
1 | let f = str => { |
如何函数体中的代码只有一句,那么大括号可以省略
1 | let f = str => console.log(str); |
如果函数体中的代码只有一个return语句,那么return关键词也必须省略
1 | //这是错误的 |
由于大括号被解释为代码块,所以如果箭头函数直接返回一个对象,必须在对象外面加上括号。
1 | let getTempItem = id => ({ id:id, name:'Temp' }) |
箭头函数有几个使用注意点。
函数体内的this对象。
函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。
或者说:箭头函数当方法使用时没有定义this绑定,而是捕获所在上下文的 this ,作为自己的 this 。1
2
3
4
5
6
7
8
9
10
11
12<button id="one">one点击(使用function)</button>
<button id="two">two点击(使用箭头函数)</button>
<script>
var one = document.getElementById('one');
var two = document.getElementById('two');
one.onclick = function (){
console.log(this); //<button id="one">one点击(使用function)</button>
}
two.onclick = ()=>{
console.log(this); //window
}
</script>注意:
- 箭头函数的this永远指向其上下文的 this。
- 普通函数的this指向调用它的那个对象。
- 不可以当作构造函数。
也就是说,不可以使用new命令,否则会抛出一个错误。 - 不可以使用arguments对象。
该对象在函数体内不存在。如果要用,可以用Rest参数代替。
箭头函数的一个用处是简化回调函数
1 | let values = [5,2,8]; |
简写简单说就是省略掉function,直接写(),或者不写;大括号可变箭头 => , 函数体只有一条可以直接写,有return就省略
rest参数与箭头函数结合
1 | <script> |
五、ES6 类(Class)
ES6提供了更接近面向对象(注意:javascript本质上是基于对象的语言)语言的写法,引入了Class(类)这个概念,作为对象的模板。通过class关键字,可以定义类。
新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。
1 | //定义类 |
上面代码定义了一个“类”,可以看到里面有一个constructor方法,这就是构造方法,而this关键字则代表实例对象。也就是说,ES5的构造函数Point,对应ES6的Point类的构造方法。
Point类除了构造方法,还定义了一个toString方法。注意,定义“类”的方法的时候,前面不需要加上function这个关键字,直接把函数定义放进去了就可以了。另外,方法之间不需要逗号分隔,加了会报错。
注意:生成类的实例对象的写法,要使用new命令。如果忘记加上new,像ES5函数那样调用Class,将会报错。
1 | // 报错 |
………..
六、ES6模块化编程
6.1 ES6模块化实现
模块功能主要由两个命令构成:export和import。
export命令用于规定模块的对外接口 。
import命令用于输入其他模块提供的功能。
1. export 命令
1 | let firstName = 'Michael'; |
在export命令后面,使用大括号指定所要输出的一组变量。
export命令除了输出变量,还可以输出函数、类(class)。
2. import命令
使用export命令定义模块对外接口后,其他 JS 文件就可以通过import命令加载这个模块。
1
2import { name, age, sex } from './module1.js‘
console.log(name + '\t' + age + '\t' + sex); 上面代码的import命令,用于加载module1.js文件,并从中输入变量。import命令接受一对大括号,里面指定要从其他模块导入的变量名。大括号里面的变量名,必须与被导入模块( module1.js)对外接口的名称相同。
import命令可以使用as关键字,将输入的变量重命名。
1
import { lastName as surname } from './profile.js
import命令具有提升效果,会提升到整个模块的头部,首先执行
1
2foo();
import { foo } from './my_module.js';上面的代码不会报错,因为import的执行早于foo的调用。这种行为的本质是,import命令是编译阶段执行的,在代码运行之前。
import是静态执行,所以不能使用表达式和变量,这些只有在运行时才能得到结果的语法结构。
1
2
3
4
5
6
7
8
9
10
11// 报错
import { 'f' + 'oo' } from './my_module.js';
// 报错
let module = ‘./my_module.js';
import { foo } from module;
// 报错
if (x === 1) {
import { foo } from './module1.js';
} else {
import { foo } from './module2.js';
}如果多次重复执行同一句import语句,那么只会执行一次,而不会执行多次
import语句是 Singleton 模式
1
2
3
4import { foo } from './my_module.js';
import { bar } from './my_module.js';
// 等同于
import { foo, bar } from './my_module.js';上面代码中,虽然foo和bar在两个语句中加载,但是它们对应的是同一个my_module实例。也就是说,import语句是 Singleton 模式。
3. 模块的整体加载
除了指定加载某个输出值,还可以使用整体加载,即用星号(*)指定一个对象,所有输出值都加载在这个对象上面。
1 | // circle.js文件 |
1 | //main.js整体加载 |