ECMASript 6
在 React 和 Vue 中使用了大量的 ES6 语法,本文简单的总结了 ES6 的一些基本特性
Babel
转码器
Babel
是一个广泛使用的 ES6 转码器,可以将 ES6 代码转为 ES5 代码,从而在现有环境执行。可通过以下命令安装在项目目录中。
1 | npm install --save-dev @babel/core |
let
与const
命令
let
命令
let 用来声明变量,用法类似于 var,但是声明的变量只在
let
命令所`在的代码块有效
const
命令
const 声明常量,一旦声明不得修改赋值,必须初始化
let const var
的区别
1、var 有变量提升,let 与 const 没有
2、var 定义的变量可以修改,如果不初始化会输出 undefined,不会报错。
3、const 定义的变量不可以修改,而且必须初始化。
4、let 是块级作用域,函数内部使用 let 定义后,对函数外部无影响。
解构赋值
ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构。
1 | var obj = { name: "老王", age: 20 }; |
扩展运算符
扩展运算符(spread)是三个点(…)。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列。
1 | let str = ["a", "b", "c"]; |
可用于复制数组
数组是复合的数据类型,直接复制的话,只是复制了指向底层数据结构的指针,而不是克隆一个全新的数组。
1 | const a1 = [1, 2]; |
模板字符串
模板字符串(template string)是增强版的字符串,用反引号(`)标识。它可以当作普通字符串使用,也可以用来定义多行字符串,或者在字符串中嵌入变量。
1 | $("#result").append( |
上面这种写法相当繁琐不方便,ES6 引入了模板字符串解决这个问题。
1 | $("#result").append(` |
模板字符串嵌入变量,需要将变量写入${}
中
1 | let name = "Bob", |
箭头函数
ES6 允许使用“箭头”(=>)定义函数。
1 | var f = () => 5; |
Symbol
ES6 引入了一种新的原始数据类型 Symbol,表示独一无二的值。它是 JavaScript 语言的第七种数据类型,前六种是:undefined、null、布尔值(Boolean)、字符串(String)、数值(Number)、对象(Object)。
Promise 对象
promis 简介
Promise 对象用于异步操作,它表示一个尚未完成且预计在未来完成的异步操作。
Promise 对象有两个特点
(1)对象的状态不受外界影响。promise 对象代表一个异步操作,分为三个状态:pending(进行中)、fulfilled(已成功)和 rejected(已失败)
(2)一旦状态改变,就不会再变,任何时候都可以得到这个结果。改变状态的两种可能:从 pending 变为 fulfilled 和从 pending 变为 rejected。
Promise 对象的缺点
(1)无法取消,一旦新建会立刻执行
(2)如果不设置回调函数,Promise 内部抛出的错误,不会反应到外部
(3)当处于 pending 状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。
Promsie 用法
Promise 对象是一个构造函数,用来生成 Promise 实例
1 | const promise = new Promise(function(resolve, reject) { |
Promise 对象接收两个参数
resolve()
在异步操作成功时调用,并将异步操作的结果,作为参数传递出去
reject()
在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
Generator 函数
Generator 函数是 ES6 提供的一种异步编程解决方案。
特征:
function 与函数名之间有个星号(*)
函数体内部使用yield
表达式
1 | function* helloWorldGenerator() { |
async 函数
async 函数就是 Generator 函数的语法糖,把 Generator 函数里面的星号(*)替换成 async,yield 替换成 await。
- await 函数返回一个 Promise 对象
1 | async function timeout(ms) { |
上面代码指定 50 毫秒以后,输出 hello world。
使用注意点
- await 返回一个 Promise 对象,所以 await 命令最好放在 try…catch 语句中
1 | const sleep = () => { |
- await 命令只能用在 async 函数之中,如果用在普通函数,就会报错。
async 函数与 Promise、Generator 函数的比较,async 函数更简洁,更具有语义,但是 async 不要滥用,会造成页面堵塞
class 继承
Class 可以通过 extends 关键字实现继承
1 | class Point {} |
上面代码定义了一个 ColorPoint 类,该类通过 extends 关键字,继承了 Point 类的所有属性和方法。但是由于没有部署任何代码,所以这两个类完全一样,等于复制了一个 Point 类。下面,我们在 ColorPoint 内部加上代码。
1 | class ColorPoint extends Point { |
上面代码中,constructor 方法和 toString 方法之中,都出现了 super 关键字,它在这里表示父类的构造函数,用来新建父类的 this 对象。
子类必须在 constructor 方法中调用 super 方法,否则新建实例时会报错。这是因为子类自己的 this 对象,必须先通过父类的构造函数完成塑造,得到与父类同样的实例属性和方法,然后再对其进行加工,加上子类自己的实例属性和方法。如果不调用 super 方法,子类就得不到 this 对象。
1 | class ColorPoint extends Point {} |
另一个需要注意的地方是,在子类的构造函数中,只有调用 super 之后,才可以使用 this 关键字,否则会报错。这是因为子类实例的构建,基于父类实例,只有 super 方法才能调用父类实例。
1 | class Point { |
上面代码中,子类的 constructor 方法没有调用 super 之前,就使用 this 关键字,结果报错,而放在 super 方法之后就是正确的。
1 | class A { |
上面代码中,hello()是 A 类的静态方法,B 继承 A,也继承了 A 的静态方法。
Object.getPrototypeOf()
Object.getPrototypeOf
方法可以用来从子类上获取父类。
1 | Object.getPrototypeOf(ColorPoint) === Point; |
因此,可以使用这个方法判断,一个类是否继承了另一个类。
super
关键字
super
既可以当函数使用,也可以当对象使用
- 当做函数调用时,代表父类的构造函数,只能用在子类的构造函数之中,用在其他地方就会报错。
1 | class A {} |
上面代码,子类 B 的构造函数中的super()
,代表调用父类的构造函数
注意,super 虽然代表了父类 A 的构造函数,但是返回的是子类 B 的实例,即 super 内部的 this 指的是 B 的实例,因此 super()在这里相当于 A.prototype.constructor.call(this)
。
super
作为对象时,在普通方法中,指向父类的原型对象;在静态方法中,指向父类。
1 | class A { |
上面代码中,子类 B 当中的 super.p(),就是将 super 当作一个对象使用。这时,super 在普通方法之中,指向A.prototype
,所以 super.p()就相当于 A.prototype.p()
。
这里需要注意,由于 super 指向父类的原型对象,所以定义在父类实例上的方法或属性,是无法通过 super 调用的。
类的 prototype
属性和__proto__
属性
(1)子类的__proto__
属性,表示构造函数的继承,总是指向父类。
(2)子类 prototype
属性的__proto__
属性,表示方法的继承,总是指向父类的
1 | class A {} |
上面代码中,子类 B 的__proto__
属性指向父类 A,子类 B 的 prototype
属性的__proto__
属性指向父类 A 的 prototype
属性。
子类实例的__proto__
属性的__proto__
属性,指向父类实例的__proto__
属性。也就是说,子类的原型的原型,是父类的原型。
1 | var p1 = new Point(2, 3); |
上面代码中,ColorPoint 继承了 Point,导致前者原型的原型是后者的原型。
因此,通过子类实例的__proto__
.__proto__
属性,可以修改父类实例的行为。
MiXin 模式的实现
Mixin 指的是多个对象合成一个新的对象,新对象具有各个组成成员的接口。它的最简单实现如下。
1 | const a = { |
上面代码中,c 对象是 a 对象和 b 对象的合成,具有两者的接口。
本文参考: 阮大神