zoukankan      html  css  js  c++  java
  • 手写call、apply,函数柯里化,promiseAll,promiseRace

    Function.prototype.myCall = function () {
      let thisVal = arguments[0] // 存call第一个参数执行上下文
      const isStrict = (function () { return this === undefined })() // 判断当前环境是否是严格模式
      if (!isStrict) { // 非严格模式
        if (thisVal === null || thisVal === undefined) { // thisVal 没传或者是null, undefined
          thisVal = (function () { return this })() // 则赋值为window或者node环境参数
        }
      } else { // 严格模式
        const thisValType = typeof thisVal // 先处理可能输入的不同数据格式
        if (thisValType === 'number') {
          thisVal = new Number(thisVal)
        }
        if (thisValType === 'string') {
          thisVal = new String(thisVal)
        }
        if (thisValType === 'boolean') {
          thisVal = new Boolean(thisVal)
        }
      }
      const otherParams = [...arguments].slice(1) // call其他参数
      const fn = this // 当前this就是调用call的方法 
      if (thisVal === null || thisVal === undefined) { // 严格模式 并且没有指定第一个参数或者第一个参数的值本身就是null或undefined,此时将目标函数当成普通函数执行并返回其结果即可
        return fn(...otherParams)
      }
      // 否则,让目标函数成为thisArg对象的成员方法,然后调用它 ???
      // 直观上来看,可以直接把目标函数赋值给对象属性,比如func属性,但是可能func属性本身就存在于thisArg对象上
      // 所以,为了防止覆盖掉thisArg对象的原有属性,必须创建一个唯一的属性名,可以用Symbol实现,如果环境不支持Symbol,可以通过uuid算法来构造一个唯一值。
      var uniquePropName = Symbol(thisVal)
      thisVal[uniquePropName] = fn
      return thisVal[uniquePropName](...otherParams)
    }
    
    Function.prototype.myApply = function () {
      let thisVal = arguments[0] // 存call第一个参数执行上下文
      const isStrict = (function () { return this === undefined })() // 判断当前环境是否是严格模式
      if (!isStrict) { // 非严格模式
        if (thisVal === null || thisVal === undefined) { // thisVal 没传或者是null, undefined
          thisVal = (function () { return this })() // 则赋值为window或者node环境参数
        }
      } else { // 严格模式
        const thisValType = typeof thisVal // 先处理可能输入的不同数据格式
        if (thisValType === 'number') {
          thisVal = new Number(thisVal)
        }
        if (thisValType === 'string') {
          thisVal = new String(thisVal)
        }
        if (thisValType === 'boolean') {
          thisVal = new Boolean(thisVal)
        }
      }
      const otherParams = Array.isArray(arguments[1]) ? [...arguments[1]] : arguments[1] // call其他参数
      const fn = this // 当前this就是调用call的方法 
      if (thisVal === null || thisVal === undefined) { // 严格模式 并且没有指定第一个参数或者第一个参数的值本身就是null或undefined,此时将目标函数当成普通函数执行并返回其结果即可
        return fn(...otherParams)
      }
      // 否则,让目标函数成为thisArg对象的成员方法,然后调用它 ???
      // 直观上来看,可以直接把目标函数赋值给对象属性,比如func属性,但是可能func属性本身就存在于thisArg对象上
      // 所以,为了防止覆盖掉thisArg对象的原有属性,必须创建一个唯一的属性名,可以用Symbol实现,如果环境不支持Symbol,可以通过uuid算法来构造一个唯一值。
      var uniquePropName = Symbol(thisVal)
      thisVal[uniquePropName] = fn
      return thisVal[uniquePropName](...otherParams)
    }
    
    function curry(fn) {
      let args = []
      function curried() {
        args = [...args, ...arguments]
        return curried
      }
      curried.toString = function(){
        return fn.myCall(null, ...args)
      }
      return curried
    }
    Promise.all = function (iterators) {
      return new Promise((resolve, reject) => {
        if (!iterators || iterators.length === 0) {
          resolve([]);
        } else {
          let count = 0; // 计数器,用于判断所有任务是否执行完成
          let result = []; // 结果数组
          for (let i = 0; i < iterators.length; i++) {
            // 考虑到iterators[i]可能是普通对象,则统一包装为Promise对象
            Promise.resolve(iterators[i]).then(
              (data) => {
                result[i] = data; // 按顺序保存对应的结果
                // 当所有任务都执行完成后,再统一返回结果
                if (++count === iterators.length) {
                  resolve(result);
                }
              },
              (err) => {
                reject(err); // 任何一个Promise对象执行失败,则调用reject()方法
                return;
              }
            );
          }
        }
      });
    };
    Promise.race = function (iterators) {
      return new Promise((resolve, reject) => {
        for (const iter of iterators) {
          Promise.resolve(iter)
            .then((res) => {
              resolve(res);
            })
            .catch((e) => {
              reject(e);
            });
        }
      });
    };
  • 相关阅读:
    11.2
    11.1
    10.31JS中级
    10.24
    动画运动
    操作js的样式
    js
    js元素属性
    js轮播
    js计时器
  • 原文地址:https://www.cnblogs.com/wilsunson/p/14453313.html
Copyright © 2011-2022 走看看