ES6.0学习

  1. 1. 一、简介
  2. 2. 二、ES6 的目标与愿景
  3. 3. 三、ES6 环境
  4. 4. 四、ES6基础
    1. 4.1. 4.1 let命令
    2. 4.2. 4.2 const 命令
    3. 4.3. 4.3 模板字符串
    4. 4.4. 4.4 rest参数
    5. 4.5. 4.5 箭头函数
  5. 5. 五、ES6 类(Class)
  6. 6. 六、ES6模块化编程
    1. 6.1. 6.1 ES6模块化实现
      1. 6.1.1. 1. export 命令
      2. 6.1.2. 2. import命令
      3. 6.1.3. 3. 模块的整体加载

一、简介

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
2
3
4
5
6
if (true) {
var a = 10;
let b = 20; // 只在if里有效
}
console.log(a); //10
console.log(b); //Uncaught ReferenceError: b is not defined

块级作用域在一些情况下,可以避免内层变量覆盖外层变量。

Let不存在变量提升

1
2
3
4
5
6
//var的情况
console.log(t1);
var t1 = 2; //undefined
//let的情况
console.log(bar);
let bar = 2; //ReferenceError: Cannot access 'bar'

控制台的输出结果:

​ 上面代码中,变量t1用var命令声明,会发生变量提升,即脚本开始运行时,变量t1已经存在了,但是没有值,所以会输出undefined。

​ 变量bar用let命令声明,不会发生变量提升。这表示在声明它之前,变量bar是不存在的,这时如果用到它,就会抛出一个错误。 因此,使用let声明变量,极大的消除了代码的潜在bug的隐患。

Let暂时性死区:

1
2
3
4
5
var temp = 123;
if(true){
temp = 'abc'; //ReferenceError: Cannot access 'temp'
let temp;
}

上面代码中,存在全局变量tmp,但是块级作用域内let又声明了一个局部变量tmp,导致后者绑定这个块级作用域,所以在let声明变量前,对tmp赋值会报错。

4.2 const 命令

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

1
2
const PI = 3.1415926;
PI = 3;

上面代码表明改变常量的值会报TypeError: Assignment to constant variable的错。

4.3 模板字符串

1
2
3
4
5
6
7
8
9
10
11
<p id="result"></p>
<script>
let basket = {
count:100,
onSale:80
}
document.getElementById('result').innerHTML =
`There are <b>${basket.count}</b> items
in your basket, <em>${basket.onSale}</em>
are on sale!`;
</script>

注意:ES6模板字符串中必须要使用反引号。

4.4 rest参数

ES6 引入 rest 参数(形式为“…变量名”),用于获取函数的多余参数。rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中。

1
2
3
4
5
6
7
8
function add(...values) {
let sum = 0;
for(var val of values) {
sum += val;
}
return sum;
}
add(2, 5, 3) // 10

上面代码的add函数是一个求和函数,利用 rest 参数,可以向该函数传入任意数目的参数。rest 参数中的变量代表一个数组,所以数组特有的方法都可以用于这个变量。

4.5 箭头函数

ES6允许使用“箭头”(=>)定义函数:

如果箭头函数不需要参数或需要多个参数,就使用一个圆括号代表参数部分

1
2
3
4
5
6
7
8
9
10
11
12
13
// 1. 不需要参数
let f = () => 5;
// 等同于
let f = function() { return 5 };

// 2. 多个参数
let sum = (num1, num2) => {
return num1 + num2;
};
// 等同于
let sum = function(num1, num2) {
return num1 + num2;
};

如果只有一个参数,那么圆括号就可以省略了

1
2
3
4
let f = str => {
console.log(str);
}
f('hello');

如何函数体中的代码只有一句,那么大括号可以省略

1
2
let f = str => console.log(str);
f('hello');

如果函数体中的代码只有一个return语句,那么return关键词也必须省略

1
2
3
4
//这是错误的
let sum = (num1, num2) => return num1 + num2;
//这是正确的
let sum = (num1, num2) => num1 + num2;

由于大括号被解释为代码块,所以如果箭头函数直接返回一个对象,必须在对象外面加上括号。

1
let getTempItem = id => ({ id:id, name:'Temp' })

箭头函数有几个使用注意点。

  1. 函数体内的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
2
3
4
5
6
7
8
let values = [5,2,8];
// function函数写法
let result = values.sort(function(a, b) {
return a - b;
});

// 箭头函数写法
let result = values.sort((a, b) => a - b);

简写简单说就是省略掉function,直接写(),或者不写;大括号可变箭头 => , 函数体只有一条可以直接写,有return就省略

rest参数与箭头函数结合

1
2
3
4
5
6
7
<script>
let numbers = (...nums) => nums;
console.log(numbers(1, 2, 3, 4, 5)); // Array(5) [ 1, 2, 3, 4, 5 ]

let headAndTail = (head, ...tail) => [head, tail];
headAndTail(1, 2, 3, 4, 5) // [1,[2,3,4,5]]
</script>

五、ES6 类(Class)

​ ES6提供了更接近面向对象(注意:javascript本质上是基于对象的语言)语言的写法,引入了Class(类)这个概念,作为对象的模板。通过class关键字,可以定义类。

​ 新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。

1
2
3
4
5
6
7
8
9
10
11
12
13
//定义类
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
toString() {
return '(' + this.x + ', ' + this.y + ')';
}
}
//创建对象
let p = new Point(1,2);
console.log(p.toString());

上面代码定义了一个“类”,可以看到里面有一个constructor方法,这就是构造方法,而this关键字则代表实例对象。也就是说,ES5的构造函数Point,对应ES6的Point类的构造方法。

Point类除了构造方法,还定义了一个toString方法。注意,定义“类”的方法的时候,前面不需要加上function这个关键字,直接把函数定义放进去了就可以了。另外,方法之间不需要逗号分隔,加了会报错

注意:生成类的实例对象的写法,要使用new命令。如果忘记加上new,像ES5函数那样调用Class,将会报错。

1
2
3
4
// 报错
let point = Point(2,3);
// 正确
let point = new Point(2,3);

​ ………..

六、ES6模块化编程

6.1 ES6模块化实现

​ 模块功能主要由两个命令构成:export和import。

​ export命令用于规定模块的对外接口 。

​ import命令用于输入其他模块提供的功能。

1. export 命令

1
2
3
4
5
6
7
8
let firstName = 'Michael';
let lastName = 'Jackson';
let year = 1958;
export {
firstName as f, //可以使用as关键字,重命名对外接口
lastName,
year
};

在export命令后面,使用大括号指定所要输出的一组变量。

export命令除了输出变量,还可以输出函数、类(class)。

2. import命令

  1. 使用export命令定义模块对外接口后,其他 JS 文件就可以通过import命令加载这个模块。

    1
    2
    import { name, age, sex } from './module1.js‘
    console.log(name + '\t' + age + '\t' + sex);

    ​ 上面代码的import命令,用于加载module1.js文件,并从中输入变量。import命令接受一对大括号,里面指定要从其他模块导入的变量名。大括号里面的变量名,必须与被导入模块( module1.js)对外接口的名称相同。

  2. import命令可以使用as关键字,将输入的变量重命名。

    1
    import { lastName as surname } from './profile.js
  3. import命令具有提升效果,会提升到整个模块的头部,首先执行

    1
    2
    foo();
    import { foo } from './my_module.js';
    1. 上面的代码不会报错,因为import的执行早于foo的调用。这种行为的本质是,import命令是编译阶段执行的,在代码运行之前。

    2. 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';
      }
    3. 如果多次重复执行同一句import语句,那么只会执行一次,而不会执行多次

    4. import语句是 Singleton 模式

      1
      2
      3
      4
      import { foo } from './my_module.js';
      import { bar } from './my_module.js';
      // 等同于
      import { foo, bar } from './my_module.js';
    5. 上面代码中,虽然foo和bar在两个语句中加载,但是它们对应的是同一个my_module实例。也就是说,import语句是 Singleton 模式。

3. 模块的整体加载

​ 除了指定加载某个输出值,还可以使用整体加载,即用星号(*)指定一个对象,所有输出值都加载在这个对象上面。

1
2
3
4
5
6
7
// circle.js文件
export function area(radius) {
return Math.PI * radius * radius;
}
export function circumference(radius) {
return 2 * Math.PI * radius;
}
1
2
3
4
//main.js整体加载
import * as circle from './circle.js';
console.log('圆面积:' + circle.area(4));
console.log('圆周长:' + circle.circumference(14));