美文网首页
JavaScript手写Api

JavaScript手写Api

作者: 六寸光阴丶 | 来源:发表于2020-06-23 19:59 被阅读0次

1. 手写instanseof方法

要求

如果是基础类型那么直接返回false,否则顺着原型链进行比对,一直到原型链为null

源码

function instance_of(L, R) {
  const baseType = ['string', 'number', 'boolean', 'undefined', 'symbol', 'bigint']
  if (baseType.includes(typeof (L))) return false
  let RP = R.prototype
  L = L.__proto__
  while (true) {
    if (L === null) return false
    else if (L === RP) return true
    else L = L.__proto__
  }
}

测试

class Person {
  constructor(_name, _age) {
    this.name = _name
    this.age = _age
  }
}
let person = new Person('name', 0)

console.log(instance_of(person, Person))
console.log(instance_of(person, Array))
console.log(instance_of([], Array))

测试结果

true
false
true

2. 手写new方法

说明

创建一个新对象,通过apply或call等方法将this绑定到新对象上。

源码

function _new (ctx, ...arg) {
  const obj = {}
  obj.__proto__ = ctx.prototype
  const res = ctx.apply(obj, arg)
  return res instanceof Object ? res : obj
}

测试

function Bar(_name, _age) {
  this.name = _name
  this.age = _age;
}
let b = _new(Bar, 'name', 20)
console.log(b)

测试结果

Bar { name: 'name', age: 20 }

3. 手写map方法

说明

遍历数组并利用参数中的函数生成一个新的数组

源码

// _this默认为本身
Array.prototype.myMap = function (fn, _this = this) {
  let arr = []
  // 遍历数组,循环对元素执行回调函数
  for (let index in this) {
    // 执行回调函数时绑定this,并将结果push进新数组
    arr.push(fn.call(_this, this[index], index, this))
  }
  // 返回新数组
  return arr
}

// 设置新增原型为不可枚举,不会被for...in遍历出来
Object.defineProperty(Array.prototype, 'myMap', {
  enumerable: false
})

测试

// 测试
let arr = [1, 2, 3]
let newarr = arr.myMap(function (item, index, _this) {
  return item + ' ' + index + ' ' + _this[index] + ' ' + this[index]
}, [7, 8, 9])
console.log(newarr)

测试结果

// [ '1 0 1 7', '2 1 2 8', '3 2 3 9' ]

4. 手写一个Promise

说明

实现基本的Promise方法

源代码

const reslovePromise = (promise2, x, reslove, reject) => {
  if (promise2 === x) {
    return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
  }
  if (x instanceof iPromise) {
    x.then.call(x, res => {
      reslovePromise(promise2, res, reslove, reject)
    }, err => {
      reject(err)
    })
  } else {
    reslove(x)
  }
}

class iPromise {
  constructor(executor) {
    this.state = 'pending'
    this.value = undefined
    this.reason = undefined
    this.onResolvedCallbacks = []
    this.onRejectedCallbacks = []

    const reslove = value => {
      if (value instanceof iPromise) {
        return value.then(reslove, reject)
      }
      setTimeout(() => {
        if (this.state === 'pending') {
          this.state = 'fulfilled'
          this.value = value
          this.onResolvedCallbacks.forEach(fn => fn())
        }
      }, 0)
    }

    const reject = reason => {
      setTimeout(() => {
        if (this.state === 'pending') {
          this.state = 'rejected'
          this.reason = reason
          this.onRejectedCallbacks.forEach(fn => fn())
        }
      }, 0)
    }

    executor(reslove, reject)
  }

  then(onFulfilled, onRejected) {
    const promise2 = new iPromise((reslove, reject) => {
      if (this.state === 'pending') {
        this.onResolvedCallbacks.push(() => {
          setTimeout(() => {
            const x = onFulfilled(this.value)
            reslovePromise(promise2, x, reslove, reject)
          }, 0)
        })
        this.onRejectedCallbacks.push(() => {
          setTimeout(() => {
            const x = onRejected(this.reason)
            reslovePromise(promise2, x, reslove, reject)
          }, 0)
        })
      }
      if (this.state === 'fulfilled') {
        setTimeout(() => {
          const x = onFulfilled(this.value)
          reslovePromise(promise2, x, reslove, reject)
        }, 0)
      }
      if (this.state === 'rejected') {
        setTimeout(() => {
          const x = onRejected(this.reason)
          reslovePromise(promise2, x, reslove, reject)
        }, 0)
      }
    })
    return promise2
  }

  static reslove(value) {
    return new iPromise((reslove, reject) => {
      reslove(value)
    })
  }

  static reject(reason) {
    return new iPromise((reslove, reject) => {
      reject(reason)
    })
  }

  static race(promises) {
    return new iPromise((resolve, reject) => {
      promises.forEach(promise => {
        promise.then(resolve, reject)
      })
    })
  }
  
  static all(promises) {
    return new Promise((res, rej) => {
      var arr = []
      var times = 0;
      function processResult(index, result) {
        arr[index] = result
        times++;
        if (times == promiseArr.length) {
          res(arr)
        }
      }

      for (let i = 0; i < promises.length; i++) {
        var oPromise = promises[i];
        if (typeof oPromise.then == 'function') {
          oPromise.then(function (val) {
            processResult(i, val)
          }, function (reason) {
            rej(reason)
          })
        } else {
          processResult(i, oPromise)
        }
      }
    })
  }
}

相关文章

网友评论

      本文标题:JavaScript手写Api

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