ECMAScript6+

新语法

  • 块级作用域变量:let const
  • 更好的unicode支持
    • 文字编码:最早的unicode指的是16位进制码元,后来unicode出现扩展集32位,占用两个码元,一个码点
    • 字符串函数 charCodeAt 读取码元
    • 新增了字符串函数 codePointAt 根据码元的位置得到其码点
//检测字符串是否是32位的
function is32bit(str, i){
    return str.codePointAt(i) > 0xffff;//0xffff是16位中的最大值,大于它则表示是32位的,小于它则是16位的
}
  • 展开运算符 ... 的使用
    • 数组展开,对数组操作时不会改变原数组
    • 接收剩余参数
  • 解构赋值
    • 数组解构
    • 对象解构
//数组解构
const arr = [1,2,3,4,5];
const [a, , c, d] = arr;//按需导入,也需要遵循顺序
const [aa, bb = 2] = arr;//给默认值
const [aaa, bbb, ...others] = arr;//剩余参数
//典型案例
let a = 1;
let b = 2;
;[b, a] = [a, b];//交换a和b的值

//对象解构
const obj = { name: 'a', age: 18 };
const { name, aa, sex = 1 } = obj;
console.log(aa)//undefined 对象解构时变量名必须和对象的属性名保持一致否则为undefined
const { name:myname } = obj;//起别名
  • 字符串新api:includes startsWith endsWith repeat
  • 箭头函数
    • 更简短的函数写法,并且不绑定this
    • 箭头函数属于匿名函数
    • this指向其所定义时的最近的作用域上下文环境中的this值
    • 不使用于构造函数、原型中的函数、字面量对象中的函数、dom事件函数
    • 没有形参列表 arguments和new.target
    • 没有原型,不能作为构造函数使用,不能使用new关键字创建实例对象

对象的变化

  • 把一个变量赋值给对象属性时,如果对象属性和变量名相同,可以省略只写一个
  • 新静态方法
    • Object.is 在===判断上做了优化
      • NaN和NaN不相等
      • 0和-0不相等
    • Object.assign 属性拷贝,合并对象
    • Object.getOwnPropertyNames 得到对象的所有属性
    • Object.setPrototypeOf 设置或修改对象原型

数组新api

  • [].forEach 无返回值
  • [].map 遍历数组处理数据,并返回新的数组
  • [].filter
  • [].every 全部符合条件返回true,否则返回false
  • [].some 有一个满足条件返回true,否则返回false
  • [].reduce
  • [].fill 填充或替换数组中所有的元素
  • [].find
  • [].findLast
  • [].findIndex
  • [].findLastIndex
  • 静态方法
    • Array.of
    • Array.from
const arr = [1,2,3,4,5];
arr.forEach((item, index, parr) => {
    //parr是当前遍历的数组 
    console.log(item)
})
arr.map((item, index) => { return {...item} })
arr.filter((item, index) => return index%2===0)
arr.every((item, index) => item > 5)
arr.some((item, index) => {})
arr.reduce((prev, next) => {
    return prev + next
}, 0)
arr.find((item, index) => index === 2)

new Array(10).fill(1)// [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]

类 class

  • 构造函数和类的区别
    • 构造函数的属性和方法一般是分开的,而类将它们统一了
    • 遍历构造函数的实例对象时,会访问到其原型上的属性
    • 类中的方法(非箭头函数)会挂在到其原型上,通过类创造的对象在遍历时不会访问其原型上的属性和方法
    • 构造函数可以当作普通函数使用,类不可以
    • 类的声明不会被提升
    • 类中的代码都会在严格模式下执行
    • 类中的方法不可以当作构造函数使用
    • 类中可使用getter和setter来控制属性
const fna = 'fna';
class Test {
    aa = 'aa'
    static bb = 'bb'//静态成员
    constructor(name, age){
        this.name = name
        this.age = age
    }
    get age(){//getter
        return this.age;
    }
    set age(age){//setter
        if(age<0){
            age = 0;
        } else if(age>100){
            age = 100;
        }
        this.age = age;
    }
    run(){// 这种方式声明的方法会挂在原型上
        console.log(this.name + '-run')
    }
    run2 = () => {//这种方式创建的方法会挂在实例对象上
        console.log(this.name + '-run')
    }
    [fna](){//可计算的成员名
        console.log('fna')
    }
}
const obj = new Test('aa', 2)
obj[fna]()
console.log(obj);//Test {aa: 'aa', name: 'aa', age: 2}

//类的表达式写法/匿名类
const Test1 = class {}
  • 类的继承:
    • extends 单继承,链式继承
    • super
      • 在constructor中直接调用会当作父类的构造函数,如果子类没有声明constructor则内部会默认自动调用
      • 当作对象使用时,表示父类的原型
class Animal {
    constructor(name, age){
        this.name = name
        this.age = age
    }
    fn(){}
}
class Dog extends Animal {
    constructor(name, age){
        super(name, age)
    }
    fn(){
        super.fn()//调用父类的方法
    }
} 

符号 Symbol

  • 新的数据类型
  • 必须通过调用Symbol函数获取一个Symbol类型的变量
  • 每次调用Symbol()得到的符号都不相等,可以利用这个特点实现对象的私有属性
  • 符号可以作为对象的属性名存在,称为符号属性
  • 共享符号:Symbol.for可以得到相同的符号,以便在不同的地方使用,称为共享符号
  • 内置符号:以下具有特殊函数的共享符号
    • 通过Symbol的静态属性获得
    • Symbol.hasInstance 构造函数隐式的私有方法用于判断一个对象是否是构造函数的实例
    • Symbol.iterator 可迭代符号
const sym = Symbol()//无参
const sym2 = Symbol('aaa')//有参
// Symbol.for('aaa')===Symbol.for('aaa')//true 通过for获取符号并且参数相同时,得到的是同一个符号
// Symbol.for()===Symbol.for()//true

console.log(typeof Symbol)//function
console.log(typeof sym)//symbol

const obj = {
    [sym]: 'xxx'//符号作为对象的属性名使用
}

//实现对象的私有属性-示例
const obj2 = (function(){
    const sym = Symbol()
    return {
        test(){
            this[sym]();//在内部使用[sym]方法
        }
        [sym](){}//外部无法调用该方法,在for in遍历中也无法访问,getOwnPropertyNames也访问不到,只能用getOwnPropertySymbols访问
    }
})()

迭代器 iterator

  • 迭代:从一个数据集合中,按顺序不断地逐个去除数据的过程
  • 迭代器:将迭代过程进行封装的形式,其实是一种设计模式,在js以对象的形式来表示
  • 如果一个对象obj有next方法,并且该方法返回一个 {value:数据,done:是否完成} 对象,则该obj对象就可以认为是一个迭代器
  • 可迭代协议:es6规定,如果一个对象有一个符号属性Symbol.iterator,并且属性是一个迭代器创建函数,则认为该对象是可迭代的
  • for(const item of 迭代器对象){} 循环就是基于迭代器做的,只要是可迭代对象都可以用for...of遍历
const obj = {
    data: [1,2,3],
    index: 0,
    [Symbol.iterator](){
        return {
            next: () => {
                const res = { value: this.data[this.index], done:this.index>=this.data.length }
                this.index++
                return res;
            }
        }
    }
}

生成器 Generator

  • 生成器:通过构造函数Generator生成的对象,这个构造函数只能由js内部new实例
  • 生成器也是一个迭代器对象,具有next方法
  • 开发时使用 * 符号即可将一个普通函数声明为生成器函数
  • 生成器函数调用时不会立即执行内部代码,只会返回一个生成器对象,生成器函数内部主要是为了给生成器的每次迭代提供数据的,每次调用生成器next方法,生成器函数就运行到下一个yield关键字位置
  • 特点:
    1. 生成器函数可以存在返回值,返回值出现在第一次done为true时到value属性中
    2. 调用生成器的next方法时可以传递参数,参数可以得到一些附加信息,传递的参数会交给yield表达式的返回值
    3. 在生成器内部可以调用其他生成器函数
  • api
    • next()
    • return() 用来控制提前结束的方法
    • throw() 返回一个错误
function * gFn(){
    console.log('bb')
    yield 'gfn';
}
function * createIterator(){
    const num = 10;
    const num2 = yield num;
    
    yield num2 + 10;//注意这里 num2的值并不是num的值10,而是第二次调用next函数时传入的值如:next(2)
    
    yield * gFn();//使用其他生成器函数

    console.log('cc')
    yield 3;
    
    return 1;//返回值
}
const it = createIterator()
it.next()
// {value: 10, done: false}
it.next(2)
// {value: 12, done: false}
it.next()
// VM300:2 bb
// {value: 'gfn', done: false}
it.next()
// VM300:15 cc
// {value: 3, done: false}
it.next()
// {value: 1, done: true}
it.next()
// {value: undefined, done: true}

异步处理

  • es6将某一件可能发生的异步操作分为两个阶段
    • unsettled 未决阶段
    • settled 已决阶段
    • es6将从未决阶段到已决阶段到过程分为三种状态:pending、resolved、rejected
  • Promise
    • 并不能消除回调,只是优化了回调地狱的可读性
    • 属于微任务
    • 原型成员
      • then
      • catch
      • finally
    • 静态成员
      • resolve(数据) 返回一个resovled状态的Promise
      • reject(数据) 返回一个rejected状态的Promise
      • all(iterable数组) 全部成功后返回resovled状态结果数组,有一个失败立即返回rejected状态错误
      • race(iterable数组) 有一个成功立即返回resovled状态结果,有一个失败立即返回rejected状态错误,不会等待后续的异步函数,即参数数组中的Promise谁先执行完毕就返回谁的结果
  • async await
    • es6 只有生成器和迭代器
    • es7 在生成器和迭代器的基础上封装了一些语法糖就是async await
    • async 修饰的函数的返回值必定是Promise对象
function fn(){
    return new Promise((resove, reject) => {
        const boo = true
        setTimeout(() => {
            if(boo){
                resove('成功')
            } else {
                reject('失败')
            }
        }, 1000);
    })
}
fn().then(res => {}, err=>{})
fn().then(res => {}).catch(err=>{}).finally((data)=>{})
async function (){
    const res = await fn();
}

const pro1 = fn()
const pro2 = fn()
Promise.all([pro1, pro2, fn()]).then(resArr=>{}).catch(err=>{})
Promise.race([pro1, pro2, fn()]).then(res=>{}).catch(err=>{})

集合

  • Set
    • new Set(iterator)
    • 内容元素不可重复,会自动去重,内部判断是否重复用的是Object.is函数
    • Set也是可迭代对象,for...of遍历
    • 属性
      • size 长度
    • 方法
      • add 添加数据
      • has 检测
      • delete 删除
      • clear 清空
      • keys
      • values
      • forEach 遍历
  • Map
    • new Map(iterator)
    • 一组键值对的集合,也是可迭代对象 for...of遍历
    • 键不可以重复,同一个键的新值会覆盖旧值,内部判断是否重复用的是Object.is函数
    • 属性:
      • size 长度
    • 方法
      • set(键,值) 设置
      • get(键) 获取值
      • has 检测
      • delete 删除
      • clear 清空
      • forEach 遍历
const s1 = new Set(...[1,2,3,4,5,5,4,3,2,1]);
const m1 = new Map([['a',1], ['b', 2]])

代理/反射

  • Reflect(反射) 内置的js对象,提供更精准地操作对象的方式
    • 用于获取、设置、检测一个js对象的元数据、方法和属性
    • Reflect.set Reflect.set
    • Reflect.apply(fn, obj, [...])
    • Reflect.defineProperty Reflect.has
  • Proxy 代理
    • 提供了修改底层实现的方式
const pObj = new Proxy({}, {
    set(target, k, v){
        console.log(target, k, v)
        Reflect.set(target, k, v);
    },
    get:function(target,prop) {
        if (prop in target) {
            return target[prop];
        } else {
            throw new ReferenceError("propertype\""+prop + "\" does no exit" );
        }
    }
})
pObj.name = 'aa';
console.log(pObj)

使用技巧

  • 数组过滤假值
const arr =[1, undefined, null, false, 0, '', 2,3].filter(Boolean)//[1,2,3]

推荐文章