ES6

ES6
TomSymbol
Symbol,新增数据类型,表示独一无二的值Symbol值通过Symbol函数生成。这就是说,对象的属性名现在可以有两种类型,一种是原来就有的字符串,另一种就是新增的 Symbol 类型。凡是属性名属于 Symbol 类型,就都是独一无二的,可以保证不会与其他属性名产生冲突。Symbol函数前不能使用 new 命令,否则会报错。因为生成的 Symbol 是一个原始类型的值,不是对象。也就是说,由于 Symbol 值不是对象,所以不能添加属性。基本上,它是一种类似于字符串的数据类型。
1 | let s = Symbol(); |
Symbol()参数
字符串: Symbol函数可以接受一个字符串作为参数,表示对 Symbol 实例的描述,主要是为了在控制台显示,或者转为字符串时,比较容易区分
1
2
3
4
5
6
7
8let s1 = Symbol('foo');
let s2 = Symbol('bar');
s1 // Symbol(foo)
s2 // Symbol(bar)
s1.toString() // "Symbol(foo)"
s2.toString() // "Symbol(bar)"对象:参数是一个对象,就会调用该对象的toString方法,将其转为字符串,然后才生成一个 Symbol 值。
1
2
3
4
5
6
7const obj = {
toString() {
return 'abc';
}
};
const sym = Symbol(obj);
sym // Symbol(abc)
注意,
Symbol()函数的参数只是表示对当前 Symbol 值的描述,因此相同参数的Symbol函数的返回值是不相等的。
Symbol运算
Symbol 值不能与其他类型的值进行运算,会报错。
1 | let sym = Symbol('My symbol'); |
Symbol 类型转换
Symbol 值可以显式转为字符串。
1
2
3
4let sym = Symbol('My symbol');
String(sym) // 'Symbol(My symbol)'
sym.toString() // 'Symbol(My symbol)'Symbol 值可以转为布尔值,但是不能转为数值。
1
2
3
4
5
6
7
8
9
10let sym = Symbol();
Boolean(sym) // true
!sym // false
if (sym) {
// ...
}
Number(sym) // TypeError
sym + 2 // TypeError
Symbol操作
在创建 Symbol 的时候,参数是为 Symbol 数据的描述。
Symbol.prototype.description返回 Symbol 的描述。
1
2const sym = Symbol('foo');
sym.description // "foo"作为属性名的 Symbol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17let mySymbol = Symbol();
// 第一种写法
let a = {};
a[mySymbol] = 'Hello!';
// 第二种写法
let a = {
[mySymbol]: 'Hello!'
};
// 第三种写法
let a = {};
Object.defineProperty(a, mySymbol, { value: 'Hello!' });
// 以上写法都得到同样结果
a[mySymbol] // "Hello!"Symbol 值作为对象属性名时,不能用点运算符。
- Symbol 作为属性名,遍历对象的时候,该属性不会出现在
for...in、for...of循环中,也不会被Object.keys()、Object.getOwnPropertyNames()、JSON.stringify()返回。
但是,它也不是私有属性,有一个Object.getOwnPropertySymbols()方法,可以获取指定对象的所有 Symbol 属性名。该方法返回一个数组,成员是当前对象的所有用作属性名的 Symbol 值。
1
2
3
4
5
6
7
8
9
10
11const obj = {};
let a = Symbol('a');
let b = Symbol('b');
obj[a] = 'Hello';
obj[b] = 'World';
const objectSymbols = Object.getOwnPropertySymbols(obj);
objectSymbols
// [Symbol(a), Symbol(b)]- Symbol 作为属性名,遍历对象的时候,该属性不会出现在
解构
ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构
1 | /**********************数组解构************************/ |
对象解构时等号左边的变量名称必须是要对象的属性值否解构不成功
解构默认值
1 | // 对象默认值 |
let/const
let关键字,用来声明变量。它的用法类似于 var,但是所声明的变量,只在 let关键字所在的代码块内有效。
不存在变量提升
var命令会发生“变量提升”现象,即变量可以在声明之前使用,值为 undefined。这种现象多多少少是有些奇怪的,按照一般的逻辑,变量应该在声明语句之后才可以使用。
为了纠正这种现象,let命令改变了语法行为,它所声明的变量一定要在声明后使用,否则报错。
var 声明的变量挂载在 window 对象下,而 let则没有。
let 不允许重复声明
作用域
ES5 只有全局作用域和函数作用域,没有块级作用域,
使用 let 关键字可以支持块级作用域。
const
const声明一个只读的常量。一旦声明,常量的值就不能改变。
模板字符串
模板字符串(template string)是增强版的字符串,用反引号(`)标识。它可以当作普通字符串使用,也可以用来定义多行字符串,或者在字符串中嵌入变量。
1 | // 字符串中嵌入变量 |
rest 参数
ES6 引入 rest 参数(形式为…变量名),用于获取函数的多余参数,这样就不需要使用arguments对象了。rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中。
1 | function add(...values) { |
… 在数组中的使用
… 在数组中时作为展开运算符使用。1
2
3
4
5
6
7
8let a = [1,2,3,4,5]
console.log(...a) // 1 2 3 4 5
let b = [6,7,8,9]
let c = [...a,...b]
console.log(...c) // [1, 2, 3, 4, 5,6, 7, 8, 9]
箭头函数
ES6 允许使用“箭头”(=>)定义函数。
1 | let f = (v)=>{ |
圆括号中定义形参列表。花括号为函数体。
箭头函数只有一个参数时 圆括号可以省略
1
2
3let f = v=>{
return v
}箭头函数,函数体中只有一条有效语句时,花括号可以省略。
1
2let f = v=>
console.log( v )箭头函数,省略花括号时如果要返回数据给调用者时不可以使用 return 关键字。
1
2let f = v=>
v // 返回数据给调用者
- 函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。
- 不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。
- 不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。
函数默认值
ES6 允许为函数的参数指定默认值。
1 | function f(num=19){ |
当调用函数时没有给函数传递实际参数时就会使用参数的默认值。
Set
ES6 提供了新的数据结构 Set()。它类似于数组,但是成员的值都是唯一的,没有重复的值。
1 | // 实例化set对象 |
set.size: 返回Set实例的成员总数。set..add(value): 添加某个值,返回 Set 结构本身。set.delete(value): 删除某个值,返回一个布尔值,表示删除是否成功。set.has(value): 返回一个布尔值,表示该值是否为Set的成员。set.clear(): 清除所有成员,没有返回值。set.keys(): 返回键名的遍历器set.values(): 返回键值的遍历器set.entries(): 返回键值对的遍历器set.forEach(): 使用回调函数遍历每个成员
1 | let set = new Set(['red', 'green', 'blue']); |
set 也可以使用展开运算符
... new Set([1,3,4,6])
Map
ES6 提供了 Map() 数据结构。它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。也就是说,Object 结构提供了“字符串—值”的对应,Map 结构提供了“值—值”的对应,是一种更完善的 Hash 结构实现。如果你需要“键值对”的数据结构,Map 比 Object 更合适。
1 | const m = new Map(); |
map.size: 属性返回 Map 结构的成员总数。map.set(key, value): set方法设置键名key对应的键值为value,然后返回整个 Map 结构。map.get(key): get方法读取key对应的键值,如果找不到key,返回undefined。map.has(key): has方法返回一个布尔值,表示某个键是否在当前Map 对象之中。map.delete(key): delete方法删除某个键,返回true。如果删除失败,返回false。map.clear(): clear方法清除所有成员,没有返回值。map.keys(): 返回键名的遍历器。map.values(): 返回键值的遍历器。map.entries(): 返回所有成员的遍历器。map.forEach(): 遍历 Map 的所有成员。
1 | const map = new Map([ |
class
ES6 提供了更接近传统语言的写法,引入了 Class(类) 这个概念,作为对象的模板。通过class关键字,可以定义类。
新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。
1 | class Human { |
class关键字表示定义一个类。constructor构造函数, 在实例化时第一个被调用的函数,成员要在constructor构造中定义。- 一个类只能有一个构造函数,如果没有定义则会自动生成一个空的
constructor。
- 一个类只能有一个构造函数,如果没有定义则会自动生成一个空的
toString成员方法。成员方法前面不能添加 function 并且成员之间不能使用 , 逗号分隔。
static 静态成员
静态方法:
- 类相当于实例的原型,所有在类中定义的方法,都会被实例继承。如果在一个方法前,加上static关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为“静态方法”。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17class Human {
constructor(name, age, sex) {
this.name = name
this.age = age
this.sex = sex
}
// 对象成员
toString() {
console.log(this.name + " : " + this.age + " : " + this.sex)
}
// 静态方法,不属于对象
static say(){
console.log('静态方法')
}
}
// 调用静态方法
Human.say()父类的静态方法,可以被子类继承。Class 内部只有静态方法,没有静态属性。
私有方法和私有属性
私有方法和私有属性,是只能在类的内部访问的方法和属性,外部不能访问。ES6 不提供私有方法和私有属性。
extends
Class 可以通过extends关键字实现继承,这比 ES5 的通过修改原型链实现继承,要清晰和方便很多。
1 | // 父类 |
super表示父类对象。super()表示父类构造方法。- 子类中如果显示包含
constructor那么必须在constructor最上方调用super()父类构造方法。实例化子类时会先实例化父类。
Promise 对象
Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。
ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象。
Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。
Promise 对象三种状态
- pending(进行中)
- fulfilled(已成功)
- rejected(已失败)
只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是Promise这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。
Promise 对象两个特点。
- 对象的状态不受外界影响。
- 一旦状态改变,就不会再变,任何时候都可以得到这个结果。
Promise 对象创建
1 | const promise = new Promise(function(resolve, reject) { |
实例化 Promise 对象时参数为一个回调函数,该回调函数有两个参数分别是 resolve和reject。
resolve(value)函数的作用是,将Promise对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;reject(value)函数的作用是,将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。promise.then()Promise实例生成以后,可以用then方法分别指定resolved状态和rejected状态的回调函数。- 参数1:成功状态触发该的回调函数
- 参数2:状态为失败触发的回调函数
then
then方法返回的是一个新的Promise实例(注意,不是原来那个Promise实例)。
1 | //监听状态发生变化 |
then方法可以返回新的promise实例,将会被下一个then所接收,注意then方法将只有一个回调,不再接收第二个回调函数。
catch
Promise.prototype.catch方法是.then(null, rejection)或.then(undefined, rejection)的别名,用于指定发生错误时的回调函数。- 使用catch方法就可以不再指定then中第二个参数,这样代码会更加易读
1 | promise |
Promise.all(iterable)
Promise.all方法常被用于处理多个promise对象的状态集合。这个方法返回一个新的promise对象,该promise对象在iterable参数对象里所有的promise对象都成功的时候才会触发成功,一旦有任何一个iterable里面的promise对象失败则立即触发该promise对象的失败。这个新的promise对象在触发成功状态以后,会把一个包含iterable里所有promise返回值的数组作为成功回调的返回值,顺序跟iterable的顺序保持一致;如果这个新的promise对象触发了失败状态,它会把iterable里第一个触发失败的promise对象的错误信息作为它的失败错误信息。
1 | function pTest(num) { |
Promise.race(iterable)
Promise.race 处理多个promise对象的状态集合时任意一个子promise成功或失败时都会返回该promise的状态 .
1 | function pTest(s) { |
async
ES2017 标准引入了 async 函数,使得异步操作变得更加方便。async 用来定义一个返回 AsyncFunction 对象的异步函数。异步函数是指通过事件循环异步执行的函数,它会通过一个隐式的 Promise 返回其结果。
基本语法
1 | async function f(num) { |
async关键字声明异步函数。async函数返回Promise对象。async函数中 使用throw触发reject(错误)状态,return触发resolve(成功)状态。
await
await 操作符用于等待一个Promise 对象。它只能在async异步函数 中使用。
1 | async function f() { |
await关键字只在异步函数内有效。如果你在async异步函数外使用它,会抛出语法错误。
await只能等待的基于promise的异步操作。await可以有多个。
Module
模块(module)体系,是将一个大程序拆分成互相依赖的小文件,再用简单的方法拼装起来
模块功能主要由两个命令构成:export和import。export命令用于规定模块的对外接口,import命令用于输入其他模块提供的功能。
<script>标签中要使用模块功能需要设置type="module"
module示例
m1.js1
2//导出模块中数据
export default { name: "小明" };main.js1
2
3//导入模块中数据
import obj from './m1.js';
console.log(obj)index.html1
2
3
4
5
6
7
8<!-- 加载一个外部文件作为模块 -->
<script type="module" src="./main.js"></script>
<!-- 在内嵌块中加载模块 -->
<script type="module">
import obj from './m1.js';
console.log(obj)
</script>











