ES6 新特性
ECMAScript 是由Ecma国际通过ECMA-262标准化的脚本程序设计语言。ES6 入门教程
let关键字
let 关键字用来声明变量,使用let 声明的变量有几个特点:
- 不允许重复声明
 - 块级作用域
 - 不存在变量提升
 - 不影响作用域链
 
const 关键字
const 关键字用来声明常量,const 声明有以下特点:
- 声明必须要赋初始值
 - 常量的名称一般大写
 - 不能修改常量的值
 - 不允许重复声明
 - 块级作用域
 
var和let的区别?
- var声明的变量没有块作用域,let声明的有块作用域
 - var可以声明同一个变量(覆盖),let不可以
 - var有变量提升,let没有
 
对象属性修改和数组元素变化不会触发 const 错误
应用场景:声明对象类型使用 const,非对象类型声明选择 let
变量的解构赋值
ES6允许按照一定模式从数组和对象中提取值,对变量进行赋值,这被称为解构赋值。
// 表示,可以从数组中提取值,按照对应位置,对变量赋值。
let [a, b, c] = [10, 20, 30];
const arr = ['宋小宝', '刘能', '赵四', '小沈阳'];
let [song, liu, zhao, xiao] = arr;
console.log(song, liu, zhao, xiao);
let {a, b} = {a: 10, b: 20};
const star = {
    name: '于谦',
    tags: ['抽烟', '喝酒', '烫头'],
    say: function () {
        console.log('我可以说相声');
    }
};
let {name, tags: [chou, he, tang], say} = star;
let obj = {a: 1, b: {c: 2}};
//标准的解构赋值
// const {c} = obj.b;
//连续解构赋值
const {b: {c}} = obj;
//连续解构赋值 + 重命名
const {b: {c: value}} = obj;
const [a, b, c, d, e] = 'hello';
a // "h"
b // "e"
c // "l"
d // "l"
e // "o"
频繁使用对象方法、数组元素,就可以使用解构赋值形式。
模板字符串
模板字符串(template string) 是增强版的字符串,用反引号(`)标识,特点:
- 字符串中可以出现换行符
 - 可以使用 
${xxx}形式输出变量 
//直接使用换行符
let str = `<ul>
            <li>沈腾</li>
            <li>玛丽</li>
            <li>艾伦</li>
            <li>魏翔</li>
        </ul>`;
//字符串中进行变量拼接
let star = '魏翔';
let str2 = `我特别喜欢${star}`;
注意:当遇到字符串与变量拼接的情况使用模板字符串
简化对象写法
ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁。
let name = 'Tom';
let pos = '北京';
let change = function () {
    console.log('改变');
};
const i = {
    name,
    pos,
    change,
    improve() {
        console.log('提升');
    }
}
箭头函数
ES6 允许使用「箭头」(=>)定义函数。
//1. 声明格式
let add = (a, b, c) => {
    return a + b + c;
};
//2. 函数调用
console.log(add(1, 2, 3));
console.log(add.call({}, 1, 2, 3));
console.log(add.apply({}, [1, 2, 3]));
箭头函数的注意点:
- 如果形参只有一个,则小括号可以省略
 - 函数体如果只有一条语句,则花括号可以省略,函数的返回值为该条语句的执行结果(如果不写花括号的话,
return也不能写) - 箭头函数 
this指向声明时所在作用域下this的值 - 箭头函数不能作为构造函数实例化
 - 箭头函数不能使用 
arguments 
注意:箭头函数不会更改this指向,所以非常适合设置与this无关的回调,比如数组回调、定时器回调,不适合事件回调与对象方法。
rest 参数
ES6引入 rest 参数,用于获取函数的实参,用来代替 arguments
function main(...args) {
    //1、使用arguments获取实参
    console.log(arguments);
    //2、rest参数
    console.log(args);
}
main(12, 23, 2, 2, 4, 12);
注意:
rest参数非常适合不定个数参数函数的场景
spread 扩展运算符
扩展运算符(spread)也是三个点(...)。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列,对数组进行解包。
//对象的展开
const skillOne = {
    q: '天音波'
};
const skillTwo = {
    w: '金钟罩'
};
const skillThree = {
    e: '天雷破'
};
const skillFour = {
    r: '猛龙摆尾'
};
const mangseng = {...skillOne, ...skillTwo, ...skillThree, ...skillFour};
console.log(mangseng);
Symbol
ES6 引入了一种新的原始数据类型 Symbol,表示独一无二的值。它是 JavaScript 语言的第七种数据类型,是一种类似于字符串的数据类型。
特点
- Symbol的值是唯一的,用来解决命名冲突的问题
 - Symbol值不能与其他数据进行运算
 - Symbol定义的对象属性不能使用
for...in循环遍历,但是可以使用Reflect.ownKeys来获取对象的所有键名 
注: Symbol类型唯一合理的用法是用变量存储
symbol的值,然后使用存储的值创建对象属性
Symbol内置值
除了定义自己使用的 Symbol 值以外,ES6 还提供了11个内置的Symbol值,指向语言内部使用的方法。
| 方法 | 作用 | 
|---|---|
| Symbol.hasInstance | 当其他对象使用instanceof运算符,判断是否为该对象的实例时,会调用这个方法 | 
| Symbol.isConcatSpreadable | 对象的Symbol.isConcatSpreadable属性等于的是一个布尔值,表示该对象用于Array.prototype.concat()时,是否可以展开。 | 
| Symbol.species | 创建衍生对象时,会使用该属性 | 
| 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. unscopables | 该对象指定了使用with关键字时,哪些属性会被with环境排除。 | 
迭代器
迭代器(Iterator)是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署 Iterator 接口,就可以完成遍历操作。
ES6创造了一种新的遍历命令for...of循环,Iterator接口主要供for...of消费
原生具备iterator接口的数据(可用for...of遍历)
- Array
 - Arguments
 - Set
 - Map
 - String
 - TypedArray
 - NodeList
 
工作原理
- 创建一个指针对象,指向当前数据结构的起始位置
 - 第一次调用对象的next方法,指针自动指向数据结构的第一个成员
 - 接下来不断调用next方法,指针一直往后移动,直到指向最后一个成员
 - 每调用next方法返回一个包含value和done属性的对象
 
注: 需要自定义遍历数据的时候,要想到迭代器。
Promise
Promise是ES6引入的异步编程的新解决方案。语法上Promise是一个构造函数,用来封装异步操作并可以获取其成功或失败的结果。
功能:写异步的代码,同步的执行出来,让代码更好的维护易读
同步:只有前一个任务执行完,才能继续执行下一个任务
异步:不进入主线程,进入任务队列,只有任务队列通知主线程,某个异步任务才可以执行,该任务才会进入主线程
- 每一个Promise实例都有3种状态:初始化(pending)、成功(fulfilled)、失败(rejected)
 - 每一个Promise实例在刚被new出来的那一刻,状态都是初始化(pending)
 - executor函数会接收到2个参数,它们都是函数,分别用形参:resolve、reject接收
 
async 和 await
async修饰的函数返回一个Promise对象,Promise实例的结果由async函数执行的返回值决定
await右侧的表达式一般为Promise实例对象, 但也可以是其它的值
- 如果表达式是Promise实例对象, await后的返回值是promise成功的值
 - 如果表达式是其它值, 直接将此值作为await的返回值
 
await必须写在async函数中, 但async函数中可以没有await
如果await的Promise实例对象失败了, 就会抛出异常, 需要通过try...catch来捕获处理
Set
ES6 提供了新的数据结构 Set(集合)。它类似于数组,『但成员的值都是唯一』的
集合实现了iterator接口,所以可以使用『扩展运算符』和for...of进行遍历
集合的属性和方法
size返回集合的元素个数add增加一个新元素,返回当前集合delete删除元素,返回boolean值has检测集合中是否包含某个元素,返回boolean值clear清空集合,返回undefined
Map
ES6 提供了 Map 数据结构。它类似于对象,也是键值对的集合。但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。
Map也实现了iterator接口,所以可以使用『扩展运算符』和for...of进行遍历。
Map的属性和方法
size返回Map的元素个数set增加一个新元素,返回当前Mapget返回键名对象的键值delete删除某个键has检测Map中是否包含某个元素,返回boolean值clear清空集合,返回undefined
class 类
ES6 提供了更接近传统语言的写法,引入了Class(类)这个概念,作为对象的模板。
通过class关键字,可以定义类。基本上,ES6 的class可以看作只是一个语法糖,它的绝大部分功能,ES5 都可以做到,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。
知识点
class声明类constructor定义构造函数初始化extends继承父类super调用父级构造方法static定义静态方法和属性- 父类方法可以重写
 get和set方法
class Person {
    constructor(name) {
        this.name = name
    }
    run() {
        return '这是run方法'
    }
}
const p = new Person('tom')
class Child extends Parent {
    constructor() {
        super()
    }
}