美文网首页
大前端——知识点回顾(ES6)

大前端——知识点回顾(ES6)

作者: 林立镇 | 来源:发表于2018-07-27 17:02 被阅读0次

    4.ES6

    谈一谈 promise

    promise和回调

    异步任务指被引擎挂起的、不在主线程上排队的任务,只有在满足某种条件后,引擎认为可以执行了,异步任务才会进入主线程
    回调函数(callback)是异步操作最基本的方法,代表着当异步操作完成就调用被传入的函数。
    Promise对象有以下两个特点:
    (1)对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是Promise这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。
    (2)一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)

    promise.all

    Promise.all可以将多个Promise实例包装成一个新的Promise实例。同时,成功和失败的返回值是不同的,成功的时候返回的是一个结果数组,而失败的时候则返回最先被reject失败状态的值。

    promise.race

    Promse.race就是赛跑的意思,意思就是说,Promise.race([p1, p2, p3])里面哪个结果获得的快,就返回那个结果,不管结果本身是成功状态还是失败状态。

    promise.resolve

    返回fulfilled状态的promise对象

    promise.reject

    返回rejected状态的promise对象

    深入解析promise源码及原理

    • 使用方式
    function buyPhone(url) {
        return new Promise(function(resolve, reject) {
            //异步请求
            http.get(url, function(error, results) {
                if (error) {
                    reject(error); 
                } else {
                    resolve(results.name) 
                }
            })
        })
    }
    buyPhone("129.168.1.1").then(function(name) {
        //一些处理
    }, function(error) {
        console.log(error)
    })
    

    promise源码

    function Promise(fn) {
        var state = 'pending',
            value = null,
            callbacks = [];
        this.then = function (onFulfilled, onRejected) {
            return new Promise(function (resolve, reject) {
                handle({
                    onFulfilled: onFulfilled || null,
                    onRejected: onRejected || null,
                    resolve: resolve,
                    reject: reject
                });
            });
        };
        function handle(callback) {
            if (state === 'pending') {
                callbacks.push(callback);
                return;
            }
            var cb = state === 'fulfilled' ? callback.onFulfilled : callback.onRejected,
                ret;
            if (cb === null) {
                cb = state === 'fulfilled' ? callback.resolve : callback.reject;
                cb(value);
                return;
            }
            try {
                ret = cb(value);
                callback.resolve(ret);
            } catch (e) {
                callback.reject(e);
            } 
        }
        function resolve(newValue) {
            if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) {
                var then = newValue.then;
                if (typeof then === 'function') {
                    then.call(newValue, resolve, reject);
                    return;
                }
            }
            state = 'fulfilled';
            value = newValue;
            execute();
        }
        function reject(reason) {
            state = 'rejected';
            value = reason;
            execute();
        }
        function execute() {
            setTimeout(function () {
                if (callbacks.length !== 0) {
                    callbacks.forEach(function (callback) {
                        handle(callback);
                    });
                }
            }, 0);
        }
        fn(resolve, reject);
    }
    

    参考:
    30分钟,让你彻底明白Promise原理

    Generator 函数

    Generator函数一个状态机,封装了多个内部状态
    还是一个遍历器对象生成函数
    两个特征。一是,function关键字与函数名之间有一个星号,二是,函数体内部使用yield语句,定义不同的内部状态
    调用Generator函数后,该函数并不知晓,返回是也不是函数运行结果,而是一个指向内部状态的指针对象,也就是遍历器对象
    必须调用遍历器对象的next方法,似的指针移动到下一个状态。

    function* helloWorldGenerator(){
      yield 'hello';
      yield 'world';
      return 'ending';
    }
    var hw = helloWorldGenerator();
    
    hw.next()
    // {value:'hello', done:false}
    hw.next()
    // {value:'world', done:false}
    hw.next()
    // {value:'ending', done:false}
    hw.next()
    // {value:undefined, done:true}
    

    async await原理

    Await和Async其实就是promise的封装,使用编译技术自动将Await/Async转化为promise
    async 函数就是 Generator 函数的语法糖。

    var gen = function* (){
       var f1,f2;
       yield f1 = readFile('/etc/fstab');
       yield f2 = readFile('/etc/shells');
      console.log(f1.toString());
      console.log(f2.toString());
    };
    vat interator = gen();
    interator.next();
    interator.next()
    interator.next()
    
    var asyncReadFile = async function (){
      var f1 = await readFile('/etc/fstab');
      var f2 = await readFile('/etc/shells');
      console.log(f1.toString());
      console.log(f2.toString());
    };
    asyncReadFile ()
    

    所有的 ES6 特性

    1. let、const
      let 定义的变量不会被变量提升,const 定义的常量不能被修改,let 和 const 都是块级作用域
      2.import、export
      import导入模块、export导出模块
    2. class、extends、super
      在一个方法前,加上static关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为“静态方法”
      Class之间可以通过extends关键字实现继承
      super关键字,它指代父类的实例(即父类的this对象)。子类必须在constructor方法中调用super方法,否则新建实例时会报错。这是因为子类没有自己的this对象,而是继承父类的this对象,然后对其进行加工。如果不调用super方法,子类就得不到this对象。
    class personner {
        constructor(name) {
            this.name = name;
        }
        sayMyself() {
            console.log("我是"+this.name)
        }
        static say() {
            console.log("名字"+this.name)
        }
    }
    personner.say()
    //名字personner
    class runner extends personner {
        constructor(name,time) {
            super(name);
            this.time = time;
        }
        run() {
            console.log(this.name+"跑步时间是"+this.time)
        }
    }
    var runnerobj = new runner("jack","12hour")
    runnerobj.run()
    //jack跑步时间是12hour
    runnerobj.sayMyself()
    //我是jack
    runner.say()
    //名字runner
    
    1. arrow functions (箭头函数)
      函数的快捷写法。不需要 function 关键字来创建函数,省略 return 关键字,继承当前上下文的 this 关键字
    2. template string (模板字符串)
      字符串拼接。将表达式嵌入字符串中进行拼接,用 和${}来界定。
    3. destructuring (解构)
      简化数组和对象中信息的提取。
      ES6前,我们一个一个获取对象信息;
      ES6后,解构能让我们从对象或者数组里取出数据存为变量
    4. default 函数默认参数
      如果一个函数的最后一个形参是以 … 为前缀的,则在函数被调用时,该形参会成为一个数组,数组中的元素都是传递给该函数的多出来的实参的值
    5. Spread Operator (展开运算符)
      组装数组,对象
    6. 对象
    • 对象初始化简写(对象属性和放值的变量相同是,可以省略冒号和值)
    • 对象字面量简写(省略冒号与 function 关键字)
    • Object.assign()
      ES6 对象提供了Object.assign()这个方法来实现浅复制。Object.assign()可以把任意多个源对象自身可枚举的属性拷贝给目标对象,然后返回目标对象。第一参数即为目标对象。在实际项目中,我们为了不改变源对象。一般会把目标对象传为{}
    const obj = Object.assign({}, objA, objB)
    // 给对象添加属性
    this.seller = Object.assign({}, this.seller, response.data)
    
    1. Promise
      用同步的方式去写异步代码
    2. Generators
      生成器( generator)是能返回一个迭代器的函数。
      生成器函数也是一种函数,最直观的表现就是比普通的function多了个星号*,在其函数体内可以使用yield关键字,有意思的是函数会在每个yield后暂停。

    es6的继承和es5的继承有什么区别

    es5的继承

    
    function Super(){
        this.flag = true;
    }
    Super.prototype.getFlag = function(){
        return this.flag;     //继承方法
    }
    function Sub(){
        this.subFlag = flase
        Super.call(this)    //继承属性
    }
    Sub.prototype = new Super;
    var obj = new Sub();
    Sub.prototype.constructor = Sub;
    Super.prototype.getSubFlag = function(){
        return this.flag;
    

    es6的继承

    
    class ColorPoint extends Point {
      constructor(x, y, color) {
        super(x, y); // 等同于parent.constructor(x, y)
        this.color = color;
      }
      toString() {
        return this.color + ' ' + super.toString(); // 等同于parent.toString()
      }
    }
    

    promise封装ajax

    ajax的xhr对象有7个事件
    onloadstart
    开始send触发
    onprogress
    从服务器上下载数据每50ms触发一次
    onload
    得到响应
    onerror
    服务器异常
    onloadend
    请求结束,无论成功失败
    onreadystatechange
    xhr.readyState改变使触发
    onabort
    调用xhr.abort时触发

    • 实现
    function ajax(optionsOverride) {
        // 将传入的参数与默认设置合并
        var options = {};
        for (var k in ajaxOptions) {
            options[k] = optionsOverride[k] || ajaxOptions[k];
        }
        options.async = options.async === false ? false : true;
        var xhr = options.xhr = options.xhr || new XMLHttpRequest();
    
        return new Promise(function (resolve, reject) {
            xhr.open(options.method, options.url, options.async);
            xhr.timeout = options.timeout;
    
            //设置请求头
            for (var k in options.headers) {
                xhr.setRuquestHeader(k, options.headers[k]);
            }
    
            // 注册xhr对象事件
            xhr.onprogress = options.onprogress;
            xhr.upload.onprogress = options.onuploadprogress;
            xhr.responseType = options.dataType;
    
            xhr.onabort = function () {
                reject(new Error({
                    errorType: 'abort_error',
                    xhr: xhr
                }));
            }
            xhr.ontimeout = function () {
                reject({
                    errorType: 'timeout_error',
                    xhr: xhr
                });
            }
            xhr.onerror = function () {
                reject({
                    errorType: 'onerror',
                    xhr: xhr
                })
            }
            xhr.onloadend = function () {
                if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304)
                    resolve(xhr);
                else
                    reject({
                        errorType: 'status_error',
                        xhr: xhr
                    })
            }
    
            try {
                xhr.send(options.data);
            }
            catch (e) {
                reject({
                    errorType: 'send_error',
                    error: e
                });
            }
        })
    }
    
    

    let const的优点

    不存在变量提升:如果变量提升,内层变量覆盖外层相同变量,所以es6不允许这种情况,es5提示undefined、es6直接报错
    .暂时性死区,绑定变量于相应块级作用域内、外部相同变量的声明无法修改作用域内变量
    .不允许重复性声明
    可以确保数据的回收,不会将子作用域的变量暴露于外层作用域中

    ES6和node的commonjs模块化规范区别

    • ES6
      export 和 import。export命令用于规定模块的对外接口,import命令用于输入其他模块提供的功能。

    • commonjs
      module、exports、require、global。实际使用时,用module.exports定义当前模块对外输出的接口(不推荐直接用exports),用require加载模块。

        //定义模块 math.js       
        var n = 0;
        function add(a, b) {
            return a + b;
        }
        module.exports = { //在这里写上需要向外暴露的函数、变量
            add: add,
            n: n
        }
    
        /** 引入模块 require **/
    
        //引用自定义的模块时,参数包含路径,可省略.js
        var math = require(‘./math‘);
        math.add(2, 5);
    
    
        //引用核心模块时,不需要带路径
        var http = require(‘http‘);
        http.createService(...).listen(3000);
    

    相关文章

      网友评论

          本文标题:大前端——知识点回顾(ES6)

          本文链接:https://www.haomeiwen.com/subject/znygmftx.html