整体流程的介绍

  • 整体流程的介绍

  • 1. 定义整体结构

  • 2. 实现Promise构造函数

  • 3. 实现then方法

  • 3.实现catch方法

  • 4. 实现Promise.resolve

  • 5.实现Promise.reject

  • 6.实现Promise.all

  • 7.实现Promise.race

文章会配合例子来讲解为什么要这么实现,尽我所能讲得粗俗易懂。有什么不理解或建议,欢迎下方评论。项目源码已经放到 github,顺手点个star呗:https://github.com/Sunny-lucking/howToBuildMyPromise

1. 定义整体结构

  1. 先写出构造函数,将Promise向外暴露
/*自定义Promise函数模块:IIFE */

(function (window) {    /*    Promise构造函数    executor:执行器函数     */    function Promise(executor) {

    }

    // 向外暴露Promise    window.Promise = Promise})()

  1. 添加Promise原型对象上的方法
 /*    Promise原型对象的then    指定一个成功/失败的回调函数    返回一个新的promise对象     */    Promise.prototype.then = function(onResolved,onRejected){

    }

    /*    Promise原型对象的.catch    指定一个失败的回调函数    返回一个新的promise对象     */    Promise.prototype.catch = function(onRejected){

    }
  1. 添加Promise函数对象上的方法
/*    Promise函数对象的resovle方法    返回一个指定结果的promise对象     */    Promise.resolve = function(value){

    }

    /*    Promise函数对象的reject方法    返回一个指定reason的失败状态的promise对象    */    Promise.reject = function(value){

    }

    /*    Promise函数对象的all方法    返回一个promise对象,只有当所有promise都成功时返回的promise状态才成功    */    Promise.all = function(0value){

    }

    /*    Promise函数对象的race方法    返回一个promise对象,状态由第一个完成的promise决定    */    Promise.race = function(value){

    }

通过上面的注释可以知道。不管是Promise原型对象上的方法还是Promise函数对象上的方法 ,它们的执行结果都将返回一个Promise对象

2. 实现Promise构造函数

我们看看我们是怎么使用Promise的

const promiseA = new Promise( (resolve,reject) => {    resolve(777);});
  1. 我们传入了一个函数,而且这个函数被立即执行,不仅如此,这个函数还会立即执行resolve和reject。说明构造函数里有resolve和reject方法。因此我们可以初步实现:
    /*    Promise构造函数    executor:执行器函数     */    function Promise(executor) {

        function resovle() {

        }        function reject() {

        }

        // 立即同步执行executor        executor(resovle,reject)    }

  1. 每个promise都有一个状态可能为pending或resolved,rejected。而且初始状态都为pending。因此需要添加个status来表示当前promise的状态.。并且每个promise有自己的data。
function Promise(executor) {

        var self = self        新增代码        self.status = 'pending' // 给promise对象指定status属性,初始值为pending

        self.data = undefined // 给promise对象指定一个存储结果的data

        function resovle() {

        }        function reject() {

        }

        // 立即同步执行executor        executor(resovle,reject)    }

此外,当我们这样使用Promise的时候,

// 例1var promise = new Promise((resovle,reject)=>{

})

promise.then(resolve=>{},reject=>{})

这时执行到then,因为我们传入的立即执行函数没有执行resolve或者reject,所以promise的状态还是pending,这时要把then里面的回调函数保存起来,所以需要个callbacks数组

function Promise(executor) {

        var self = self

        self.status = 'pending' // 给promise对象指定status属性,初始值为pending        self.data = undefined // 给promise对象指定一个存储结果的data        新增代码        self.callbacks = []  // 每个元素的结构:{onResolved(){},onRejected(){}}

        function resovle() {

        }        function reject() {

        }

        // 立即同步执行executor        executor(resovle,reject)    }

那 then函数是怎么把传入的回调收集起来的。其实很简单,就是判断当前promise是否为pending状态,是的话,就把回调push到callbacks中。

Promise.prototype.then = function(onResolved,onRejected){

        var self = this

        if(self.status === 'pending'){            // promise当前状态还是pending状态,将回调函数保存起来            self.callbacks.push({                onResolved(){onResolved(self.data)},                onRejected(){onRejected(self.data)}            })        }else if(self.status === 'resolved'){        }else{        }

    }
  1. 在上面的例子1的基础上,当我们执行resovle(value)时,如例2
// 例2var promise = new Promise((resolve,reject)=>{    setTimeout(function () {        resolve(1)    })})

promise.then(    value=>{console.log(value)},    err=>{console.log(err)}    )

此时代码执行情况是怎么样的呢?

  1. 先执行new Promise里的代码,然后发现个定时器,js线程将定时器交给定时器线程处理,2. 然后继续执行下面的代码,发现是then,而且当前的promise还是pending的状态。就把then里的回调函数放到callbacks中。
  2. 5秒后定时器线程将定时器里的回调函数(也就是宏任务)放到消息队列中,js线程在消息队列里发现了这个宏任务,就把它拿来执行。
  3. 执行这个宏任务,就执行了resolve(1),此时promise的callbacks里的回调被执行。并将当前promise状态改为resolved。然后这个1也会被保存到当前promise对象中

那怎么实现resolve呢?依旧上面的描述,就知道resovle的功能是执行callbacks里的函数,并保存data并将当前promise状态改为resolved。所以我们可以这么实现

function resolve(value) {    // 将状态改为resolved    self.status = 'resolved'    // 保存value的值    self.data = value

    // 如果有待执行的callback函数,立即异步执行回调函数onResolved    if (self.callbacks.length>0){        self.callbacks.forEach(callbackObj=>{            callbackObj.onResolved(value)        })    }}
  1. 我们还知道,promise的状态只能改变一次,因此当执行resolve的时候要判断是不是promise是不是pending的状态,否则是不能执行的
function resolve(value) {    // 如果当前状态不是pending,则不执行    if(this.status !== 'pending'){        return     }    // 将状态改为resolved    this.status = 'resolved'    // 保存value的值    this.data = value

    // 如果有待执行的callback函数,立即异步执行回调函数onResolved    if (this.callbacks.length>0){        setTimeout(()=>{            this.callbacks.forEach(callbackObj=>{ A                callbackObj.onResolved(value)            })        })    }}
  1. 异曲同工之妙的是reject方法也是这个道理,因此这里无需赘述
function reject(value) {    // 如果当前状态不是pending,则不执行    if(self.status !== 'pending'){        return    }    // 将状态改为rejected    self.status = 'rejected'    // 保存value的值    self.data = value

    // 如果有待执行的callback函数,立即异步执行回调函数onResolved    if (self.callbacks.length>0){      self.callbacks.forEach(callbackObj=>{          callbackObj.onRejected(value)      })    }}
  1. 我们又知道,当在执行executor的时候,如果执行异常的话,这个promise的状态会直接执行reject方法。例如
// 例 3var promise = new Promise((resolve,reject)=>{

    error;执行到这里出错了

    setTimeout(function () {        resolve(1)    })})

要实现这个功能,我们可以在executor外让try catch来捕获

try{    // 立即同步执行executor    executor(resolve,reject)}catch (e) { // 如果执行器抛出异常,promise对象变为rejected状态    reject(e)}

好了,现在测试下

 // 例4 let promise = new Promise((resolve,reject)=>{

        setTimeout(function () {            resolve(1)            //reject(1)        },100)    })

    promise.then(        value=>{            console.log("onResolved:",value);        },        reason=>{            console.log("onRejected:",reason);        }    )

发现成功。成功输出onResolved:1

3. 实现then方法

我们在上面简单的实现了当前promise为pending状态的情况,如:

Promise.prototype.then = function(onResolved,onRejected){

    var self = this

    if(self.status === 'pending'){        // promise当前状态还是pending状态,将回调函数保存起来        self.callbacks.push({            onResolved(){onResolved(self.data)},            onRejected(){onRejected(self.data)}        })    }else if(self.status === 'resolved'){    }else{    }

}

那其他情况呢?

执行到then时,promise可能会是pending状态,此时就要把then里的回调函数保存起来,也可能会是resolved或者rejected状态,此时就不用把回调保存起来,直接执行onResolved或onRejected方法。注意是异步执行。而且是做为微任务的,这里我们简单的用setTimeout来实现就好了。

Promise.prototype.then = function(onResolved,onRejected){

  var self = this

  if(self.status === 'pending'){      // promise当前状态还是pending状态,将回调函数保存起来      self.callbacks.push({          onResolved(){onResolved(self.data)},          onRejected(){onRejected(self.data)}      })  }else if(self.status === 'resolved'){      setTimeout(()=>{          onResolved(self.data)      })  }else{      setTimeout(()=>{          onResolved(self.data)      })  }

}

而且我们知道,执行完then是要返回一个新的promise的,而新的promise的状态则由当前then的执行结果来确定。

 Promise.prototype.then = function(onResolved,onRejected){

    var self = this

    return new Promise((resolve,reject)=>{        if(self.status === 'pending'){            // promise当前状态还是pending状态,将回调函数保存起来            self.callbacks.push({                onResolved(){onResolved(self.data)},                onRejected(){onRejected(self.data)}            })        }else if(self.status === 'resolved'){            setTimeout(()=>{                onResolved(self.data)            })        }else{            setTimeout(()=>{                onResolved(self.data)            })        }    })

}

当 当前的promise状态为resolved的时候,则执行then的时候,会执行第二个判断语句

则当前执行第二个判断语句的时候会出现三种情况

  1. 如果then里的回调函数返回的不是promise,return的新promise的状态是则是resolved,value就是返回的值。例如:
// 例5let promise = new Promise((resolve,reject)=>{    resolve(1)})

promise.then(    value=>{        return value //返回的不是promise,是value    })

因此,我们可以这样实现

Promise.prototype.then = function(onResolved,onRejected){

    var self = this

    return new Promise((resolve,reject)=>{        if(self.status === 'pending'){            // promise当前状态还是pending状态,将回调函数保存起来            self.callbacks.push({                onResolved(){onResolved(self.data)},                onRejected(){onRejected(self.data)}            })        }else if(self.status === 'resolved'){            修改代码            setTimeout(()=>{                const result = onResolved(self.data)                if (result instanceof Promise){

                } else {                // 1. 如果回调函数返回的不是promise,return的promise的状态是resolved,value就是返回的值。                    resolve(result)                }            })        }else{            setTimeout(()=>{                onResolved(self.data)            })        }    })

}

简单解释下:

执行onResolved(self.data),其实就是执行例子中的下面这个回调函数

value=>{        return value //返回的不是promise,是value    }

那么这个回调函数返回了value。就把value传入resolve函数,resolve函数将当前新的promise的状态改为resolved,同时将value保存到当前新的promise的data中。

  1. 如果回调函数返回的是promise,return的promise的结果就是这个promise的结果,如代码所示,我们返回一个新的promise。如果这个promise执行了resolve,返回的新的promise的状态则是resolved的。否则为rejected
// 例6let promise = new Promise((resolve,reject)=>{    resolve(1)})

promise.then(    value=>{        return new Promise((resolve,reject)=>{            resolve(2)            //或者            //reject(error)        })    })

因此我们可以这样实现

Promise.prototype.then = function(onResolved,onRejected){

    var self = this

    return new Promise((resolve,reject)=>{        if(self.status === 'pending'){            // promise当前状态还是pending状态,将回调函数保存起来            self.callbacks.push({                onResolved(){onResolved(self.data)},                onRejected(){onRejected(self.data)}            })        }else if(self.status === 'resolved'){            setTimeout(()=>{                const result = onResolved(self.data)                if (result instanceof Promise){                    // 2. 如果回调函数返回的是promise,return的promise的结果就是这个promise的结果                    result.then(                        value => {resolve(value)},                        reason => {reject(reason)}                    )                } else {                    // 1. 如果回调函数返回的不是promise,return的promise的状态是resolved,value就是返回的值。                    resolve(result)                }            })        }else{            setTimeout(()=>{                onResolved(self.data)            })        }    })

}

在这里说明一下:

result.then(    value => {resolve(value)},    reason => {reject(reason)})

由于我们在例6中执行了then里的

value=>{        return new Promise((resolve,reject)=>{            resolve(2)            //或者            //reject(error)        })    }

则返回一个promise对象,这个promise对象可能为resolved状态(执行 resolve(2))也可能为rejected状态(执行reject(error))。

将会导致value => {resolve(value)},这个回调函数的执行或者reason => {reject(reason)}的执行。

因此会把即将返回的新的promise的data设置为value或者,reason。会把状态设置为resolved或者rejected。

  1. 如果执行这段代码的时候抛出错误,则返回的promise的状态为rejected,我们可以用try catch来实现
setTimeout(()=>{    try{        const result = onResolved(self.data)        if (result instanceof Promise){            // 2. 如果回调函数返回的是promise,return的promise的结果就是这个promise的结果            result.then(                value => {resolve(value)},                reason => {reject(reason)}            )        } else {            // 1. 如果回调函数返回的不是promise,return的promise的状态是resolved,value就是返回的值。            resolve(result)        }    }catch (e) {      //  3.如果执行onResolved的时候抛出错误,则返回的promise的状态为rejected        reject(e)    }})

异曲同工之妙的是当status === 'rejected',道理一样

 setTimeout(()=>{      try{          const result = onRejected(self.data)          if (result instanceof Promise){              // 2. 如果回调函数返回的是promise,return的promise的结果就是这个promise的结果              result.then(                  value => {resolve(value)},                  reason => {reject(reason)}              )          } else {              // 1. 如果回调函数返回的不是promise,return的promise的状态是resolved,value就是返回的值。              resolve(result)          }      }catch (e) {          //  3.如果执行onResolved的时候抛出错误,则返回的promise的状态为rejected          reject(e)      }  })

到这里,我们发现当执行resolve的时候,onResolved(self.data)onRejected(self.data)执行时也会跟上面一样的结果,可以说执行回调函数都要做以上判断,因此我们要将

 self.callbacks.push({    onResolved(){onResolved(self.data)},    onRejected(){onRejected(self.data)}})

改成

if(self.status === 'pending'){// promise当前状态还是pending状态,将回调函数保存起来self.callbacks.push({    onResolved(){        try{            const result = onResolved(self.data)            if (result instanceof Promise){                // 2. 如果回调函数返回的是promise,return的promise的结果就是这个promise的结果                result.then(                    value => {resolve(value)},                    reason => {reject(reason)}                )            } else {                // 1. 如果回调函数返回的不是promise,return的promise的状态是resolved,value就是返回的值。                resolve(result)            }        }catch (e) {            //  3.如果执行onResolved的时候抛出错误,则返回的promise的状态为rejected            reject(e)        }    },

到此,我们发现,相同的代码太多了,因此有必要封装一下

 function handle(callback) {    try{        const result = callback(self.data)        if (result instanceof Promise){            // 2. 如果回调函数返回的是promise,return的promise的结果就是这个promise的结果            result.then(                value => {resolve(value)},                reason => {reject(reason)}            )        } else {            // 1. 如果回调函数返回的不是promise,return的promise的状态是resolved,value就是返回的值。            resolve(result)        }    }catch (e) {        //  3.如果执行onResolved的时候抛出错误,则返回的promise的状态为rejected        reject(e)    }}

这样以来就清爽了很多

   Promise.prototype.then = function(onResolved,onRejected){

        var self = this

        return new Promise((resolve,reject)=>{           /*            调用指定回调函数的处理,根据执行结果。改变return的promise状态             */            function handle(callback) {                try{                    const result = callback(self.data)                    if (result instanceof Promise){                        // 2. 如果回调函数返回的是promise,return的promise的结果就是这个promise的结果                        result.then(                            value => {resolve(value)},                            reason => {reject(reason)}                        )                    } else {                        // 1. 如果回调函数返回的不是promise,return的promise的状态是resolved,value就是返回的值。                        resolve(result)                    }                }catch (e) {                    //  3.如果执行onResolved的时候抛出错误,则返回的promise的状态为rejected                    reject(e)                }            }            if(self.status === 'pending'){                // promise当前状态还是pending状态,将回调函数保存起来                self.callbacks.push({                    onResolved(){                        handle(onResolved)                    },                    onRejected(){                        handle(onRejected)                    }                })            }else if(self.status === 'resolved'){                setTimeout(()=>{                    handle(onResolved)                })            }else{ // 当status === 'rejected'                setTimeout(()=>{                    handle(onRejected)                })            }        })

    }

另外,我们还知道,promise会发生值传透,例如

let promsie = new Promise((resolve,reject)=>{    resolve(1)})promsie  .then(2)  .then(3)  .then(value =>console.log(value))

运行结果:1

解释:.then 或者 .catch 的参数期望是函数,传入非函数则会发生值穿透。值传透可以理解为,当传入then的不是函数的时候,这个then是无效的。而实际原理上其实是当then中传入的不算函数,则这个then返回的promise的data,将会保存上一个的promise.data。这就是发生值穿透的原因。而且每一个无效的then所返回的promise的状态都为resolved

因此,要实现直传透这个特性,我们可以这样实现

添加这两句来判断要不要发生值传透

onResolved = typeof onResolved === 'function'? onResolved: value => valueonRejected = typeof onRejected === 'function'? onRejected: reason => {throw reason}

实际上就是改写,如果传入的不是函数,那就忽略那个传入值,自己再写一个函数。这个函数的执行结果将返回上一个promise的data

Promise.prototype.then = function(onResolved,onRejected){    onResolved = typeof onResolved === 'function'? onResolved: value => value    onRejected = typeof onRejected === 'function'? onRejected: reason => {throw reason}    var self = this

    return new Promise((resolve,reject)=>{

        /*        调用指定回调函数的处理,根据执行结果。改变return的promise状态         */        function handle(callback) {            try{                const result = callback(self.data)                if (result instanceof Promise){                    // 2. 如果回调函数返回的是promise,return的promise的结果就是这个promise的结果                    result.then(                        value => {resolve(value)},                        reason => {reject(reason)}                    )                } else {                    // 1. 如果回调函数返回的不是promise,return的promise的状态是resolved,value就是返回的值。                    resolve(result)                }            }catch (e) {                //  3.如果执行onResolved的时候抛出错误,则返回的promise的状态为rejected                reject(e)            }        }        if(self.status === 'pending'){            // promise当前状态还是pending状态,将回调函数保存起来            self.callbacks.push({                onResolved(){                    handle(onResolved)                },                onRejected(){                    handle(onRejected)                }            })        }else if(self.status === 'resolved'){            setTimeout(()=>{                handle(onResolved)            })        }else{ // 当status === 'rejected'            setTimeout(()=>{                handle(onRejected)            })        }    })

}

3.实现catch方法

catch方法的作用跟then里的第二歌回调函数一样,因此我们可以这样来实现

Promise.prototype.catch = function(onRejected){    return this.then(undefined,onRejected)}

我的天啊,居然这么简单

4. 实现Promise.resolve

我们都知道,Promise.resolve方法可以传三种值

  1. 不是promise
  2. 成功状态的promise
  3. 失败状态的promise
    Promise.resolve(1)    Promise.resolve(Promise.resolve(1))    Promise.resolve(Promise.reject(1))

实际上跟实现上面的then时有点像

Promise.resolve = function(value){  return new Promise((resolve,reject)=>{      if (value instanceof Promise){          // 如果value 是promise          value.then(              value => {resolve(value)},              reason => {reject(reason)}          )      } else{          // 如果value不是promise          resolve(value)      }

  }

}

5.实现Promise.reject

实现这个比较简单,返回一个状态为rejected的promise就好了

/*Promise函数对象的reject方法返回一个指定reason的失败状态的promise对象*/Promise.reject = function(reason){    return new Promise((resolve,reject)=>{        reject(reason)    })}

6.实现Promise.all

我们知道,这个方法会返回一个promise

    /*    Promise函数对象的all方法    返回一个promise对象,只有当所有promise都成功时返回的promise状态才成功    */    Promise.all = function(promises){        return new Promise((resolve,reject)=>{

        })    }

而这个promise的状态由遍历每个promise产生的结果决定

    /*    Promise函数对象的all方法    返回一个promise对象,只有当所有promise都成功时返回的promise状态才成功    */    Promise.all = function(promises){        return new Promise((resolve,reject)=>{            // 遍历promises,获取每个promise的结果            promises.forEach((p,index)=>{

            })        })    }

有两种结果:

  1. 遍历到有一个promise是reject状态,则直接返回的promise状态为rejected
 Promise.all = function(promises){        return new Promise((resolve,reject)=>{            // 遍历promises,获取每个promise的结果            promises.forEach((p,index)=>{                p.then(                    value => {

                    },                    reason => { //只要有一个失败,return的promise状态就为reject                        reject(reason)                    }                )            })        })    }
  1. 遍历所有的promise的状态都为resolved,则返回的promise状态为resolved,并且还要每个promise产生的值传递下去
   Promise.all = function(promises){      const values = new Array(promises.length)      var resolvedCount = 0 //计状态为resolved的promise的数量      return new Promise((resolve,reject)=>{          // 遍历promises,获取每个promise的结果          promises.forEach((p,index)=>{              p.then(                  value => {                      // p状态为resolved,将值保存起来                      values[index] = value                      resolvedCount++;                      // 如果全部p都为resolved状态,return的promise状态为resolved                      if(resolvedCount === promises.length){                          resolve(values)                      }                  },                  reason => { //只要有一个失败,return的promise状态就为reject                      reject(reason)                  }              )          })      })  }

好像可以了,当其实这里还有一个问题,就是all传进去的数组不一定都是promise对象,可能是这样的

all([p,2,3,p])

因此需要把不是promise的数字包装成promise

    Promise.all = function(promises){        const values = new Array(promises.length)        var resolvedCount = 0 //计状态为resolved的promise的数量        return new Promise((resolve,reject)=>{            // 遍历promises,获取每个promise的结果            promises.forEach((p,index)=>{                Promise.resolve(p).then(                    value => {                        // p状态为resolved,将值保存起来                        values[index] = value                        resolvedCount++;                        // 如果全部p都为resolved状态,return的promise状态为resolved                        if(resolvedCount === promises.length){                            resolve(values)                        }                    },                    reason => { //只要有一个失败,return的promise状态就为reject                        reject(reason)                    }                )            })        })    }

7.实现Promise.race

这个方法的实现要比all简单很多

  /*    Promise函数对象的race方法    返回一个promise对象,状态由第一个完成的promise决定    */    Promise.race = function(promises){        return new Promise((resolve,reject)=>{            // 遍历promises,获取每个promise的结果            promises.forEach((p,index)=>{                Promise.resolve(p).then(                    value => {                        // 只要有一个成功,返回的promise的状态九尾resolved                        resolve(value)

                    },                    reason => { //只要有一个失败,return的promise状态就为reject                        reject(reason)                    }                )            })        })    }

有什么不理解或建议,欢迎下方评论。项目源码已经放到github:https://github.com/Sunny-lucking/howToBuildMyPromise  顺手点个star呗

去做一下题,看看是不是真的掌握了呢?【建议星星】要就来45道Promise面试题一次爽到底(1.1w字用心整理)

之前可能会出现有些题不会做,而当你阅读完这篇文章后,再去做,发现易如反掌。

定时器和promise_手写Promise核心原理,再也不怕面试官问我Promise原理相关推荐

  1. babel原理_手写webpack核心原理,再也不怕面试官问我webpack原理

    手写webpack核心原理 一.核心打包原理 1.1 打包的主要流程如下 1.2 具体细节 二.基本准备工作 三.获取模块内容 四.分析模块 五.收集依赖 六.ES6转成ES5(AST) 七.递归获取 ...

  2. 手写Vuex核心原理,再也不怕面试官问我Vuex原理

    手写Vuex核心原理 文章目录 手写Vuex核心原理 一.核心原理 二.基本准备工作 三.剖析Vuex本质 四.分析Vue.use 五.完善install方法 六.实现Vuex的state 七.实现g ...

  3. 图解红黑树原理,再也不怕面试被问到,不详细算我输!

    前言 最近针对互联网公司面试问到的知识点,总结出了Java程序员面试涉及到的绝大部分面试题及答案分享给大家,希望能帮助到你面试前的复习且找到一个好的工作,也节省你在网上搜索资料的时间来学习. 内容涵盖 ...

  4. 实战系列-被面试官问到Feign原理

    导语   事情是这样的,昨天参加了某公司二面,被面试官问道了Spring Cloud的RESTFul远程调用.项目上用到的技术就是OpenFeign,面试官可能自己不是太了解,给他解释一番发现自己还有 ...

  5. 15w+字的计算机网络知识核心总结!再也不怕面试官问我网络知识了,飘了!

    大家好,我是小林. 我在 csdn 输出了 15w+ 的图解网络系列文章,每一篇文章都有我高清无ma的手绘图. 每一篇都相当干活,很多同学跟我说,我的图解网络打破了他们对计算机网络的恐惧,甚至还助力他 ...

  6. Git | 面试官问你 Git 原理,你能回答得出来吗?

    文章目录 原创声明 前言 一.Git 简单介绍 二.解开 Git 在日常上班操作中的神秘面纱 2.1 初始化仓库 git init 2.2 第n次提交 git add xxx git status g ...

  7. 手写Redux核心原理

    手写Redux核心原理 一.createStore核心逻辑实现 createStore的三个参数 reducer:根据actions类型对store中数据状态进行更改,返回一个新的状态 preload ...

  8. 手写Hooks核心原理

    手写实现useState useEffect useReducer 一. useState 钩子函数的实现原理 // import { useState } from 'react' import R ...

  9. 一起手写Vue3核心模块源码,掌握阅读源码的正确方法

    最近和一个猎头聊天,说到现在前端供需脱节的境况.一方面用人方招不到想要的中高级前端,另一方面市场上有大量初级前端薪资要不上价. 特别是用 Vue 框架的,因为好上手,所以很多人将 Vue 作为入门框架 ...

最新文章

  1. java爬树方法_Java-grandMother.java
  2. 列名必须是一个字符串或者数组_我爱Julia之入门-078(字符串08)
  3. Git下载与使用(Git地址由CSDN提供)
  4. [BZOJ2324][ZJOI2011][最小费用最大流]营救皮卡丘
  5. Topk 问题详解及代码和数据分析
  6. 谈一下我对如何设计微服务接口的理解和思考
  7. jpa基于按annotation的hibernate主键生成策略
  8. mac上Matlab怎么运行不了,解决macOS系统下matlab无法访问中文路径及中文乱码问题...
  9. Oracle SQL查询,日期过滤条件要注意的一点
  10. ACM模板(Java)
  11. ubuntu运行c/c++语言
  12. Qt - 自定义窗口 点击窗口外自动关闭
  13. dcm文件如何转化为jpg或者bmp文件
  14. ADB的使用-简单命令
  15. Excel 常用的九十九个技巧 Office 自学教程快速掌握办公技巧
  16. 在手机相册(ios设备相册)中创建相册
  17. Oracle-----同义词索引
  18. Docker提交天池比赛流程
  19. python统计中文字符数量
  20. CGO arm 树莓pi下的交叉编译

热门文章

  1. 东华大学计算机学院讲座单,计信学院成功举办2018级专业导师面对面系列讲座活动...
  2. keyshot环境素材文件_KeyShot渲染,打光这么打,效果倍儿棒
  3. python 代码格式规范脚本_Python编码规范
  4. 视频光端机园区出入口监控项目应用方案详解
  5. 工业以太网交换机的三种转发方式
  6. 【渝粤教育】国家开放大学2018年秋季 3950T金融基础 参考试题
  7. 【渝粤教育】电大中专电商运营实操 (15)作业 题库
  8. 【渝粤教育】广东开放大学 云计算技术与应用 形成性考核
  9. 蓝桥杯基础模块2:蜂鸣器继电器
  10. MATLAB下数组随机打乱顺序的方法