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

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))