ES6
let
- 变量不能重复声明
- 块级作用域(只在代码块中有效,外部就会无效)
- 不存在变量提升(不允许在变量声明之前,使用这个变量)
- 不影响作用域链
- 暂时性死区(只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响)
const
用来声明常量(值不能修改的称为常量)
- 一定要赋初始值
- 一般常量使用大写(潜规则,小写也可以)
- 常量值不能修改
- 块级作用域
- 对于数组和对象的元素修改,不算对常量的修改,不会报错。所以数据,对象创建时建议使用const
例:const ARR = [1,2,3];arr.push(4) 不会报错,原因是因为ARR指向的地址没有发生改变,发生改变的只是数组数据
变量结构赋值
ES6允许按照一定模式从数组和对象中提取值,对变量进行赋值,称为解构赋值
- 数组的解构
- 对象解构赋值
模板字符串 ``
- 内容中可以直接出现换行符
- 可以直接进行变量拼接
简化对象写法
ES6允许在大括号里,直接写入变量和函数,作为对象的属性和方法
箭头函数 =>
箭头函数适合与this无关的回调,定时器,数组方法的回调。不适合与this有关的回调,事件回调,对象的方法
- this是静态的,始终指向函数声明时所在作用域下的this的值,call和apply都不能改变指针的指向
- 不能作为构造函数实例化对象
- 不能使用arguments变量(arguments是用来保存实参的)
- 省略小括号,当形参有且只有一个是时候
- 省略花括号,当代码体只有一条语句的时候,此时return必须也省略,而且语句的执行结果就是函数的返回值
允许给函数参数赋值初始值
- 形参初始值,具有默认值的参数,一般位置要靠后(潜规则)
- 默认值可以与解构赋值同时使用
引入rest参数,用于获取函数的实参,用来代替arguments
- ES5
- ES6
- rest参数必须放到参数的后面,否则会报错
扩展运算符 ...
扩展运算符能将数组转换为逗号分隔的参数序列
应用
- 数组的合并
- 数组的克隆(浅拷贝)
- 将伪数组转为真正的数组
Symbol
表示独一无二的值,它是js的第七种数据类型,是一种类似字符串的数据类型
特性
- Symbol的值时唯一的,用来解决命名冲突问题
- Symbol值不能与其他数据进行运算(不能进行隐式类型转换)
- Symbol定义的对象属性不能使用for...in循环遍历,但是可以使用Reflect.ownKeys来获取对象的所有键名
- Symbol 函数栈不能用 new 命令,因为 Symbol 是原始数据类型,不是对象
创建
使用场景
向对象中添加属性和方法,表示独一无二的
- 安全的向一个对象中添加属性方法,不会影响到这个对象中本身的数据
- 在写一个对象的时候,想为一个对象添加一个独一无二的属性
Symbol属性
除了定义自己使用的Symbol值以外,ES6还提供了内置的Symbol值,执行语言内部使用的方法。 可以称这些方法为魔术方法,因为它们会在特定的场 景下自动执行。
| 属性值 | 说明 |
|---|---|
| Symbol.hasInstance | 当其他对象使用instanceof运算符,判断是否为该对象的实例时,会调用这个方法(可以控制返回的结果) |
| Symbol.isConcatSpreadable | 对象的Symbol.isConcatSpreadable属性等于的是一个布尔值,表示该对象用于Array.prototype.concat()时,是否可以展开 |
| Symbol.unscopables | 该对象指定了使用with关键字时,哪些属性会被with环境排除 |
| Symbol.match | 当执行str.match(myObject)时,如果该属性存在,会调用他,返回该方法的返回值 |
| Symbol.replace | 当该对象呗str.replace(myObject)方法调用时,会返回该方法的返回值 |
| Symbol.search | 当该对象被str.search(myObject)方法调用时,会返回该方法的返回值 |
| Symbol.split | 当该对象被str.split(myObject)方法调用时,会返回该方法的返回值 |
| Symbol.iterator | 对象进行for...of循环时,会调用Symbol.iterator方法,返回该对象的默认遍历器 |
| Symbol.toPrimitive | 该对象被转为原始类型的值时,会调用这个方法,返回该对象对应的原始类型值 |
| Symbol.toStringTag | 在该对象上调用toString方法时,返回该方法的返回值 |
| Symbol.species | 创建衍生对象时,会使用该属性 |
Symbol方法
- Symbol.for()
用于将描述相同的Symbol变量指向同一个Symbol值
- Symbol.keyFor()
用来检测该字符串参数作为名称的 Symbol 值是否已被登记,返回一个已登记的 Symbol 类型值的 key
a1已经用Symbol.for()登记过,因此返回的key为"a",而a2没有被登记,因此返回undefined
Symbol.for() 和 Symbol的区别
相同点
- 它们定义的值类型都为"symbol"
不同点
- Symbol()定义的值每次都是新建,即使描述相同值也不相等
- Symbol.for()定义的值会先检查给定的描述是否已经存在,如果不存在才会新建一个值,并把这个值登记在全局环境中供搜索,Symbol.for()定义相同描述的值时会被搜索到,描述相同则他们就是同一个值
迭代器(Iterator)
是一种接口,为各种不同的数据结构提供统一的访问机制,任何数据结构只要部署Iterator接口,就可以完成遍历操作(Iterator 接口的目的,就是为所有数据结构,提供了一种统一的访问机制,即for...of循环)
- ES6创造了一种新的遍历命令for...of循环,Iterator接口(指的是对象里的属性Symbol.iterator)主要供for...of消费
- 原生具备Iterator接口的数据(可用for...of遍历)
-
- Array、Arguments、Set、Map、String、TypedArray、NodeList
特点
for...of循环调用遍历器接口,数组的遍历器接口只返回具有数字索引的属性。这一点跟for...in循环也不一样
上述代码中,for...of循环不会返回数组arr的foo属性
Iterator 接口的目的
就是为所有数据结构,提供了一种统一的访问机制,即for...of循环。当使用for...of循环遍历某种数据结构时,该循环会自动去寻找 Iterator 接口
工作原理
- 创建一个指针对象,指向当前数据结构的起始位置
- 第一次调用对象的next方法,指针自动指向数据结构的第一个成员
- 接下来不断调用next方法,指针一直往后移动,知道指向最后一个成员
- 每调用next方法返回一个包含value和done属性的对象
应用
- 实现自定义的遍历数据,对对象的遍历,对banji对象部署Iterator接口,Symbol.iterator属性对应一个函数,执行后返回当前对象的遍历器对象
- 对于类似数组的对象(存在数值键名和length属性,字符串、DOM NodeList 对象、arguments对象),部署 Iterator 接口,有一个简便方法,就是Symbol.iterator方法直接引用数组的 Iterator 接口
默认调用 Iterator 接口(即Symbol.iterator方法)
- 解构赋值
- 扩展运算符
- yield*
- 其他场合:由于数组的遍历会调用遍历器接口,所以任何接受数组作为参数的场合,其实都调用了遍历器接口
遍历器对象的 return(),throw()
- return()
使用场合是,如果for...of循环提前退出(通常是因为出错,或者有break语句),就会调用return()方法。如果一个对象在完成遍历前,需要清理或释放资源,就可以部署return()方法
注意,return()方法必须返回一个对象,这是 Generator 语法决定的
![]()
上述代码中,情况一输出文件的第一行以后,就会执行return()方法,关闭这个文件;情况二会在执行return()方法关闭文件之后,再抛出错误
- throw()
主要是配合 Generator 函数使用,一般的遍历器对象用不到这个方法
与其他遍历语法的比较:以数组为例
- for...in循环可以遍历数组的键名
缺点
- 数组的键名是数字,但是for...in循环是以字符串作为键名“0”、“1”、“2”等等
- for...in循环不仅遍历数字键名,还会遍历手动添加的其他键,甚至包括原型链上的键
- 某些情况下,for...in循环会以任意顺序遍历键名
- for...in循环主要是为遍历对象而设计的,不适用于遍历数组
-
for循环
-
for...of循环可以遍历数组的键值
- 有着同for...in一样的简洁语法,但是没有for...in那些缺点
- 不同于forEach方法,它可以与break、continue和return配合使用
- 提供了遍历所有数据结构的统一操作接口
Generator 生成器
生成器函数是ES6提供的一种异步编程解决方案,语法行为与传统函数完全不同
特性
- function关键字与函数名之间有一个星号
- 函数体内部使用yield表达式,定义不同的内部状态(yield在英语里的意思就是“产出”)
必须调用遍历器对象的next方法,使得指针移向下一个状态。也就是说,每次调用next方法,内部指针就从函数头部或上一次停下来的地方开始执行,直到遇到下一个yield表达式(或return语句)为止。换言之,Generator 函数是分段执行的,yield表达式是暂停执行的标记,而next方法可以恢复执行
生成器的函数参数
异步操作的实例
next方法
next方法可以带一个参数,该参数就会被当作上一个yield表达式的返回值(next方法返回的是yield后面的东西)不传参就返回对应的那一次(每一次的next对应的是每一次yield,但是传参之后的值是上一次yield的结果而已,next对应的还是相对应的yield)
![]()
Generator.prototype.throw()
上述代码中,遍历器对象i连续抛出两个错误。第一个错误被 Generator 函数体内的catch语句捕获。i第二次抛出错误,由于 Generator 函数内部的catch语句已经执行过了,不会再捕捉到这个错误了,所以这个错误就被抛出了 Generator 函数体,被函数体外的catch语句捕获
throw方法可以接受一个参数,该参数会被catch语句接收,建议抛出Error对象的实例
不要混淆遍历器对象的throw方法和全局的throw命令。上面代码的错误,是用遍历器对象的throw方法抛出的,而不是用throw命令抛出的。后者只能被函数体外的catch语句捕获
Generator.prototype.return()
可以返回给定的值,并且终结遍历 Generator 函数
next()、throw()、return() 的共同点
它们的作用都是让 Generator 函数恢复执行,并且使用不同的语句替换yield表达式
- next()是将yield表达式替换成一个值
上述代码中,第二个next(1)方法就相当于将yield表达式替换成一个值1。如果next方法没有参数,就相当于替换成undefined
- throw()是将yield表达式替换成一个throw语句
- return()是将yield表达式替换成一个return语句
Promise
是ES6引入的异步编程的新解决方案。语法上Promise是一个构造函数,功能上用来封装异步操作并可以获取其成功或失败的结果
方法
then
then方法返回的是一个promise对象,对象状态(成功,失败)是由回调函数(then内函数的执行结果)的执行结果决定
- 如果回调函数中返回结果是 非promise类型的数据,那么对象状态为成功,返回值为对象成功的值(若不return一个值,就会默认返回一个undefined)
- 如果返回的是一个promise对象,内部返回的promise的状态,就决定then方法返回的状态,返回值就是内部promise的返回值
- 抛出错误,返回的是失败的状态,返回值时错误信息
catch
promise对象失败的回调
all
参数接收一个数组,返回一个promise,只有当所有promise都成功时才成功,否则只要有一个失败的就失败
![]()
race
参数接收一个数组,返回一个promise,其结果由第一个完成的promise决定
![]()
语法糖
- Promise.resolve()
- Promise.reject()
手写Promise实现
Set
Map
class
ES5和ES6中实例化对象的方式
-
ES5中实例化对象的方式
-
ES6中使用class实例化对象的方式
-
静态成员
ES5构造函数的继承和ES6的class继承
- ES5
- ES6
注意:子类是不能直接调用父类中同名的方法的,比如在ChildPhone中声明call(),会将父类的中call重写,在调用的时候,是调用的子类中的方法
get和set
get通常对动态属性进行封装,比如计数,set可以添加控制判断,比如判断添加的值是否符合设定的规则
![]()
数值扩展
- Number.EPSOLON
- Number.isFinite:检测一个数值是否为有限数
- Number.isNaN:检测一个数值是否是NaN
- Number.parseInt和Number.parseFloat:字符串转整数/浮点数
- Number.isInteger:判断一个数值是否为整数
- Math.trunc:将数值的小数部分抹掉
- Math.sign:判断一个数值是正数(1)、负数(-1)还是零(0)
对象方法扩展
- Object.is:判断两个值是否完全相等
- Object.assign:对象的合并
- Object.setPrototypeOf 和 Object.getPrototypeOf
==================================