ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

js高级用法----手写js原生方法

2020-11-20 14:04:11  阅读:200  来源: 互联网

标签:function MyPromise resolve value js ---- reason reject 手写


1、call 方法

/**
 * _call
 *
 * @param { context } context
 * @param { arguments } arguments
 */
Function.prototype._call = function(context) {
  // 如果没有传或传的值为空对象 context指向window
  context = context || window
  let fn = Symbol(context)
  context[fn] = this //给context添加一个方法 指向this
  // 处理参数 去除第一个参数this 其它传入fn函数
  let args = [...arguments].slice(1) //[...xxx]把类数组变成数组,arguments为啥不是数组自行搜索 slice返回一个新数组
  context[fn](...args) //执行fn
  delete context[fn] //删除方法
}

var obj = {
    name: 'Bob',
    age: '18',
    fn() {
        console.log(`My name is ${this.name}, my age is ${this.age}`)
    }
}

var dog = {
    name: 'Snoopy',
    age: 3
}
obj.fn.call(dog,'daddata','ttt','yuyuyuuy') // My name is Snoby, my age is 3
obj.fn._call(dog,'daddata','ttt','yuyuyuuy') // My name is Snoby, my age is 3

2、 apply 方法

Function.prototype._apply = function(context) {
    // 如果没有传或传的值为空对象 context指向window
    context = context || window
    let fn = Symbol(context)
    context[fn] = this 
    let arg = [...arguments].slice(1) 
    context[fn](arg) //执行fn
    delete context[fn] //删除方法
}

3、bind方法

/**
 * _bind
 *
 * @param {*} context
 */
Function.prototype._bind = function (context) {
  //返回一个绑定this的函数,我们需要在此保存this
  let self = this
  // 可以支持柯里化传参,保存参数
  let arg = [...arguments].slice(1)
  // 返回一个函数
  return function () {
    //同样因为支持柯里化形式传参我们需要再次获取存储参数
    let newArg = [...arguments]
    // 返回函数绑定this,传入两次保存的参数
    //考虑返回函数有返回值做了return
    return self.apply(context, arg.concat(newArg))
  }
}

4、promise方法

function MyPromise(exceptor) {
  let _this = this;
  _this.reason = '';
  _this.value = '';
  _this.resolveFnArr = [];
  _this.rejectFnArr = [];
  _this.status = 'pending';
  function resolve(val) {
    if (_this.status === 'pending') {
      _this.value = val;
      _this.status = 'fulfiled';
      _this.resolveFnArr.forEach(fn => fn())
    }
  }

  function reject(reason) {
    if (_this.status === 'pending') {
      _this.reason = reason;
      _this.status = 'reject';
      _this.rejectFnArr.forEach(fn => fn())
    }
  }

  try {
    exceptor(resolve, reject);
  } catch (error) {
    reject();
  }
}

MyPromise.prototype.then = function(resolve, reject) {
  let _this = this;
  if (_this.status === 'fulfiled') {
    resolve(_this.value);
  }
  if (_this.status === 'reject') {
    reject(_this.reason);
  }

  if (_this.status === 'pending') {
    _this.resolveFnArr.push(() => {resolve(_this.value)})
    _this.rejectFnArr.push(() => {reject(_this.reason)})
  }
}

5、全面的promise写法

(function(window,undefined){
 
  // resolve 和 reject 最终都会调用该函数
  var final = function(status,value){
      var _this = this, fn, status;
   
      if(_this._status !== 'PENDING') return;
   
      // 所以的执行都是异步调用,保证then是先执行的
      setTimeout(function(){
          _this._status = status;
          status = _this._status === 'FULFILLED'
          queue = _this[status ? '_resolves' : '_rejects'];
   
          while(fn = queue.shift()) {
              value = fn.call(_this, value) || value;
          }
   
          _this[status ? '_value' : '_reason'] = value;
          _this['_resolves'] = _this['_rejects'] = undefined;
      });
  }
   
   
  //参数是一个函数,内部提供两个函数作为该函数的参数,分别是resolve 和 reject
  var MyPromise = function(resolver){
      if (!(typeof resolver === 'function' ))
          throw new TypeError('You must pass a resolver function as the first argument to the promise constructor');
      //如果不是promise实例,就new一个
      if(!(this instanceof MyPromise)) return new MyPromise(resolver);
   
      var _this = this;
      _this._value;
      _this._reason;
      _this._status = 'PENDING';
      //存储状态
      _this._resolves = [];
      _this._rejects = [];
   
      //
      var resolve = function(value) {
          //由於apply參數是數組
          final.apply(_this,['FULFILLED'].concat([value]));
      }
   
      var reject = function(reason){
          final.apply(_this,['REJECTED'].concat([reason]));
      }
   
      resolver(resolve,reject);
  }
   
  MyPromise.prototype.then = function(onFulfilled,onRejected){
      var _this = this;
      // 每次返回一个promise,保证是可thenable的
      return new MyPromise(function(resolve,reject){
   
          function handle(value) {
              // 這一步很關鍵,只有這樣才可以將值傳遞給下一個resolve
              var ret = typeof onFulfilled === 'function' && onFulfilled(value) || value;
   
              //判断是不是promise 对象
              if (ret && typeof ret ['then'] == 'function') {
                  ret.then(function(value) {
                      resolve(value);
                  }, function(reason) {
                      reject(reason);
                  });
              } else {
                  resolve(ret);
              }
          }
   
          function errback(reason){
              reason = typeof onRejected === 'function' && onRejected(reason) || reason;
              reject(reason);
          }
   
          if(_this._status === 'PENDING'){
              _this._resolves.push(handle);
              _this._rejects.push(errback);
          }else if(_this._status === FULFILLED){ // 状态改变后的then操作,立刻执行
              callback(_this._value);
          }else if(_this._status === REJECTED){
              errback(_this._reason);
          }
      });
  }
   
  MyPromise.prototype.catch = function(onRejected){
      return this.then(undefined, onRejected)
  }
   
  MyPromise.prototype.delay = function(ms,value){
      return this.then(function(ori){
          return MyPromise.delay(ms,value || ori);
      })
  }
   
  MyPromise.delay = function(ms,value){
      return new MyPromise(function(resolve,reject){
          setTimeout(function(){
              resolve(value);
              console.log('1');
          },ms);
      })
  }
   
  MyPromise.resolve = function(arg){
      return new MyPromise(function(resolve,reject){
          resolve(arg)
      })
  }
   
  MyPromise.reject = function(arg){
      return MyPromise(function(resolve,reject){
          reject(arg)
      })
  }
   
  MyPromise.all = function(promises){
      if (!Array.isArray(promises)) {
          throw new TypeError('You must pass an array to all.');
      }
      return MyPromise(function(resolve,reject){
          var i = 0,
              result = [],
              len = promises.length,
              count = len
   
          //这里与race中的函数相比,多了一层嵌套,要传入index
          function resolver(index) {
            return function(value) {
              resolveAll(index, value);
            };
          }
   
          function rejecter(reason){
              reject(reason);
          }
   
          function resolveAll(index,value){
              result[index] = value;
              if( --count == 0){
                  resolve(result)
              }
          }
   
          for (; i < len; i++) {
              promises[i].then(resolver(i),rejecter);
          }
      });
  }
   
  MyPromise.race = function(promises){
      if (!Array.isArray(promises)) {
          throw new TypeError('You must pass an array to race.');
      }
      return MyPromise(function(resolve,reject){
          var i = 0,
              len = promises.length;
   
          function resolver(value) {
              resolve(value);
          }
   
          function rejecter(reason){
              reject(reason);
          }
   
          for (; i < len; i++) {
              promises[i].then(resolver,rejecter);
          }
      });
  }
   
  window.MyPromise = MyPromise;
   
  })(window);

 

标签:function,MyPromise,resolve,value,js,----,reason,reject,手写
来源: https://www.cnblogs.com/zhangycun/p/14010488.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有