js基础之ES6新增知识点总结

135 阅读7分钟

一、模板字符串

如:

`Welcome ${uname}`

注意:${}里可以放:变量、算术计算、三目、对象属性、创建对象、调用函数、访问数组元素——有返回值的合法的js表达式。- 不能放没有返回值的js表达式,也不能放分支/判断、循环等程序结构。比如: if else for while...

二、let和const

let的优点

不会被声明提前,保证程序顺序执行。让程序块,也变成了”块级作用域”。保证块内的变量,不会影响块外的变量。

let的本质

底层会被翻译为匿名函数自调:

(function(){})()

let和const的三个特点:

  1. 因为不会声明提前,所以不能在声明变量之前,提前使用该变量。
  2. 在相同作用域内,禁止声明两个同名的变量!
  3. 因为let底层相当于匿名函数自调,所以,即使在全局创建的let变量,在window中也找不到!

var, let, const区别

区别varletcoust
是否产生”块级作用域”×
是否会被声明提前××
是否保存在window中××
相同作用域中能否重复声明变量××
是否能提前使用××
是否必须设置初始值××
能否修改实际保存在变量中的原始类型值或引用类型地址×

三、箭头函数

优点:简单
缺点:

  • 构造函数不能用
  • 对象的方法不能用
  • 原型对象方法不能用
  • DOM中事件处理函数不能用
  • 箭头函数无法用call,apply,bind改变this
  • 箭头函数不支持arguments
  • 箭头函数没有prototype

四、for of

今后只要遍历数字下标的东西,都可用for of代理普通for循环和forEach

普通for循环

  • 优点: 既可遍历索引数组,又可以遍历类数组对象(arguments)——只要下标是数字
  • 缺点: 没有可简化的空间

forEach

  • 优点: 可以配合ES6的箭头函数,很简化
  • 缺点: 只能遍历数字下标的索引数组,无法遍历类数组对象

for of的问题

  • 无法获得下标位置i,只能获得元素值
  • 无法控制遍历的顺序或步调,只能从头到尾,一个挨一个的顺序遍历
  • 无法遍历下标名为自定义下标的对象和关联数组

普通for,forEach,for of, for in的区别

遍历对象普通forforEachfor offor in
索引数组×
类数组对象××
关联数组×××
对象×××

总结:下标为数字,首选for of;下标为自定义字符串,首选for in

五、参数增强

1、默认参数值

如:

function order(
yinliao="鸡腿“
){ … }

2、剩余参数(rest)

优点:

  • 支持箭头函数
  • 生成的数组是纯正的数组类型,所以使用数组家所有函数
  • 自定义数组名arr,比arguments简单的多!

3、展开运算符(spread)

如:

// 合并多个数组和元素
var arr1=[1,2,3];
var arr2=[5,6,7];
var arr3=[...arr1,4,...arr2,8];
// 合并多个对象和属性
var obj1={ x:1, y:2 };
var obj2={ i:4, j:5 };
var obj3={...obj1, z:3, ...obj2, k:6};

六、解构(destruct)

旧js中,要想使用对象中的成员,或数组中的元素,都必须带着"对象名."或"数组名[]"前缀。 实际开发中,对象或数组的嵌套结构可能很深。前缀就可能写很长: “对象名.属性名.更子一级属性名....”, • 非常麻烦。 所以,以后遇到一个复杂的对象或数组时,都可以通过解构方式,来减少数组或对象的嵌套结构便于使用

七、Class

旧js中,构造函数和原型对象是分开定义的。不符合"封装"概念。 今后,只要在es6中创建一种新的类型,包含构造函数+原型对象方法,都要用class来创建

八、Promise

实际开发中,经常需要让多个异步任务顺序执行,但异步函数几乎同时执行,各自执行各自的,互不干扰,互相之间也不会等待。 旧js的做法是利用回调函数,但如果要先后执行的任务多了!就会形成很深的嵌套结构 ——回调地狱。极其不优雅,极其不便于维护,所以Promise解决了回调地狱的问题

Promise三大状态:

  • pending(挂起)
  • fulfilled(成功)
  • rejected(出错)

手动实现Promise对象:

var PENDING = 0; //挂起状态
var FULFILLED = 1; //执行成功状态
var REJECTED = 2; //执行失败状态
//定义Promise构造函数,将来用new创建Promise对象
function Promise() {
    // state变量存储当前Promise对象的执行状态
    var state = PENDING;
    // value变量存储执行成功后的返回值,或执行失败后的错误提示信息
    var value = null;
    // handlers变量是一个数组,存储将来用.then()函数传入的一个或多个后续任务函数。
    var handlers = [];
    doResolve(fn, resolve, reject);
    function fulfill(result) { //执行成功后,把状态改为成功状态,并把执行结果返回值,保存在变量value中
        state = FULFILLED;
        value = result;
    }
    function reject(error) { //执行失败后,把状态改为失败状态,并把错误提示信息,保存在变量value中
        state = REJECTED;
        value = error;
    }
    function resolve(result) { //如果当前任务成功执行完成,使用者调用了resolve(返回值)
    try {
        var then = getThen(result); //就要收集当前Promise对象身上后续的.then()函数中传入的内容
        if (then) { //如果有.then
        //就调用核心doResolve函数,执行.then()中的函数,并传入两个状态切换函数。
        doResolve(then.bind(result), resolve, reject) //resolve和doResolve之间的递归用来处理promise的层层嵌套
        return
        }
        //如果没有.then,就直接切换当前Promise对象的状态,并返回执行结果,结束当前Promise对象的执行
        fulfill(result);
        } catch (e) {
            //如果调用过程中出错,就调用reject()函数,将当前Promise状态切换为失败,并返回错误提示信息
            reject(e);
        }
    }
    function handle(handler) {
        if (state === PENDING) {
            handlers.push(handler);
        } else {
            if (state === FULFILLED &&typeof handler.onFulfilled === 'function') {
                handler.onFulfilled(value);
            }
            if (state === REJECTED &&typeof handler.onRejected === 'function') {
                handler.onRejected(value);
            }
        }
    }
    this.done = function (onFulfilled, onRejected) {
        // 使用定时器,确保当前任务一定是异步执行的
        setTimeout(function () {
        handle({ //传入修改状态的两个回调函数
        onFulfilled: onFulfilled,
        onRejected: onRejected
        });
        }, 0);
    }
    this.then = function (onFulfilled, onRejected) {
        var self = this; //保存当前Promise对象
        return new Promise(function (resolve, reject) { //创建并返回下一个Promise对象
        return self.done(
        function (result) { //调用当前对象的done()函数
        if (typeof onFulfilled === ‘function’) { //如果.then()中传入的是一个函数
        try {
        return resolve(onFulfilled(result)); //就调用resolve,传入下一项任务的函数,执行。
        } catch (ex) { return reject(ex);}
        } else {
        return resolve(result); //否则就传入下一个Promise对象,继续等待。
        }
        }, 
        function (error) {
        if (typeof onRejected === 'function') {
        try {
        return resolve(onRejected(error));
        } catch (ex) {return reject(ex);}
        } else {
        return reject(error);
        }
    }
}

/**
* .then()函数中传入的内容有两种情况: 可能传入的是下一个Promise对象,也可能直接传入匿名函数
* 如果调用resolve时传入的是下一个Promise对象,
* 就返回这个Promise对象的.then()函数.
* 如果调用resolve时传入的是下一个函数
* 就直接返回这个函数即可
* 如果调用resolve时什么都没传,就返回null
*/
function getThen(value) {
    var t = typeof value; 
    if (value && (t === 'object' || t === 'function')) { 
        var then = value.then; 
        if (typeof then === 'function') { 
            return then; 
        } 
    } 
    return null;
}
/**
* 调用传入的.then()函数,并传入执行成功和执行失败两个修改状态的回调函数*/
function doResolve(fn, onFulfilled, onRejected) {
    var done = false; //默认暂时未执行成功
    try {
    fn( //调用当前任务函数
    function (value) { //传入执行成功后,请使用者主动调用的res函数
    if (done) return //如果done被标记为true,说明当前异步任务执行完
    done = true //否则如果done暂时未被标记为true, 就标记为true,让当前异步任务状态变为完成状态
    onFulfilled(value) //调用传入的第一步定义的改变当前Promise状态的函数,把当前Promise对象标记为执行成功,并保存返回值
    //这里调用了resolve函数。
    }, 
    function (reason) {//传入执行失败后,请使用者主动调用的resolve函数
    if (done) return //如果done被标记为true,说明当前异步任务执行完
    done = true //否则如果done暂时未被标记为true,就标记为true,让当前异步任务状态变为完成状态
    onRejected(reason) //调用传入的第一步定义的改变当前Promise状态的函数,把当前Promise对象标记为执行失败,并保存错误提示
    })
    } catch (ex) { //如果出现异常
        if (done) return //如果done被标记为true,说明当前异步任务执行完,就退出当前任务的执行
        done = true //否则如果done暂时未被标记为true,就标记为true。
        onRejected(ex) //调用传入的改变状态函数,把当前Promise对象标记为执行失败
    }
}