手写各种函数

60 阅读5分钟

手写一个call方法

// 手写一个call方法
Function.prototype.myCall = function (context,...args) {
  // 判断调用对象是否为函数
  if (typeof this!== 'function') {
    console.error('type error')
  }
  // 获取参数
  let context = context || window
  context.fn = this
  let result = context.fn(...args)// 执行当前函数
  delete context.fn
  return result
}

手写一个apply方法

// 手写一个apply方法-- this,[]/类数组
Function.prototype.myApply = function (context,args) {
  // 判断调用对象是否为函数
  if (typeof this!== 'function') {
    console.error('type error')
  }
  // 获取参数
  let context = context || window
  context.fn = this
  let result
  // 判断是否传入了参数
  if (args) {
    result = context.fn(...args)
  } else {
    result = context.fn()
  }
  delete context.fn
  return result
}

手写一个bind方法

// 手写一个bind方法
Function.prototype.myBind = function (context,...args) {
  // 判断调用对象是否为函数
  if (typeof this!== 'function') {
    throw new TypeError('type error')
  }
  let self = this
  // 获取参数
  let args1 = args || []
  return function Fn(...args2) {
    // 根据调用方式,传入不同绑定值
    if (this instanceof Fn) {
      return self.apply(this,args1.concat(args2))
    } else {
      return self.apply(context,args1.concat(args2))
    }
  }
}
// 手写一个bind方法
Function.prototype.myBind2 = function (context,...args) {
  // 判断调用对象是否为函数
  if (typeof this!== 'function') {
    throw new TypeError('type error')
  }
  let self = this
  // 获取参数
  let args1 = args || []
  return function Fn(...args2) {
    // 根据调用方式,传入不同绑定值
    // if (this instanceof Fn) {
    //   return self.apply(this,args1.concat(args2))
    // } else {
      return self.apply(context,args1.concat(args2))
    // }
  }
}

手写一个instanceof方法

// 手写一个instanceof方法
function myInstanceof(left,right) {
  // 这里先用typeof来判断基础数据类型,如果是,直接返回false
  if (typeof left!== 'object' || left === null) return false
  // getProtypeOf是Object对象自带的API,能够拿到参数的原型对象
  let proto = Object.getPrototypeOf(left)
  while (true) {
    if (proto === null) return false
    if (proto === right.prototype) return true
    proto = Object.getPrototypeOf(proto)
  }
}

手写一个new方法

// 手写一个new方法
function myNew(fn,...args) {
  // 创建一个空对象
  let obj = {}
  // 链接到原型
  obj.__proto__ = fn.prototype
  // 绑定this,执行构造函数
  let result = fn.apply(obj,args)
  // 确保返回值为对象
  return result instanceof Object? result : obj
}

手写一个深拷贝方法

// 手写一个深拷贝方法
function deepClone(obj,hash = new WeakMap()) {
  // 对引用类型进行拷贝
  if (obj.constructor === Date) return new Date(obj)
  if (obj.constructor === RegExp) return new RegExp(obj)
  // 如果循环引用了就用 weakMap 来解决
  if (hash.has(obj)) return hash.get(obj)
  let allDesc = Object.getOwnPropertyDescriptors(obj)
  // 遍历传入参数所有键的特性
  let cloneObj = Object.create(Object.getPrototypeOf(obj),allDesc)
  // 继承原型链
  hash.set(obj,cloneObj)
  for (let key in cloneObj) {
    // 递归
    cloneObj[key] = deepClone(obj[key],hash)
  }
  return cloneObj
}

手写一个浅拷贝方法

// 手写一个浅拷贝方法
function shallowClone(obj) {
  // 只拷贝实例属性和方法
  if (typeof obj!== 'object') return
  // 基于obj的类型判断是新建一个数组还是对象
  let newObj = obj instanceof Array? [] : {}
  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
      newObj[key] = obj[key]
    }
  }
  return newObj
}

手写一个防抖方法

// 手写一个防抖方法
function debounce(fn,wait) {
  let timeout = null
  return function () {
    if (timeout!== null) clearTimeout(timeout)
    timeout = setTimeout(fn,wait)
  }
}

手写一个节流方法

// 手写一个节流方法
function throttle(fn,wait) {
  let timeout = null
  return function () {
    if (!timeout) {
      timeout = setTimeout(() => {
        timeout = null
        fn.apply(this,arguments)
      },wait)
    }
  }
}

手写一个Promise方法

// 手写一个Promise方法
function myPromise(fn) {
  // 定义常量
  const PENDING = 'pending'
  const FULFILLED = 'fulfilled'
  const REJECTED = 'rejected'
  // resolve和reject为什么要用箭头函数?
  // 如果直接调用的话,普通函数this指向的是window或者undefined
  // 用箭头函数就可以让this指向当前实例对象
  // 成功之后的值
  let value = null
  // 失败之后的原因
  let reason = null
  // 状态
  let state = PENDING
  // 成功回调
  let onFulfilledCallbacks = []
  // 失败回调
  let onRejectedCallbacks = []
  // resolve函数,成功时调用
  let resolve = (val) => {
    // 状态为pending时才可以改变状态,
    if (state === PENDING) {
      // resolve调用后,状态改为成功
      state = FULFILLED
      // 保存成功之后的值
      value = val
      // 成功回调是微任务队列执行
      setTimeout(() => {
        onFulfilledCallbacks.forEach(fn => fn())
      })
    }
  }
  // reject函数,失败时调用
  let reject = (val) => {
    // 状态为pending时才可以改变状态,
    if (state === PENDING) {
      // resolve调用后,状态改为失败
      state = REJECTED
      // 保存失败之后的原因
      reason = val
      // 失败回调是微任务队列执行
      setTimeout(() => {
        onRejectedCallbacks.forEach(fn => fn())
      })
    }
  }
  // 执行传进来的函数
  try {
    fn(resolve,reject)
  } catch (e) {
    // 有错误就直接执行reject
    reject(e)
  }
  // then方法,根据状态调用成功回调或失败回调
  this.then = (onFulfilled,onRejected) => {
    // 判断状态
    if (state === FULFILLED) {
      // 调用成功回调,并且把值返回
      onFulfilled(value)
    } else if (state === REJECTED) {
      // 调用失败回调,并且把原因返回
      onRejected(reason)
    } else if (state === PENDING) {
      // 因为不知道后面状态的变化情况,所以将成功回调和失败回调存储起来
      // 等到执行成功失败函数的时候再传递
      onFulfilledCallbacks.push(() => {
        onFulfilled(value)
      })
      onRejectedCallbacks.push(() => {
        onRejected(reason)
      })
    }
  }
}

手写一个Promise.all方法

// 手写一个Promise.all方法
function myPromiseAll(promises) {
  // 返回一个新的promise对象
  return new myPromise((resolve,reject) => {
    let count = 0
    let result = []
    for (let i = 0; i < promises.length; i++) {
      // promises[i] 可能不是promise,所以要加一层判断
      myPromise.resolve(promises[i]).then((data) => {
        count++
        result[i] = data
        // 所有的promise都执行完了就resolve
        if (count === promises.length) {
          resolve(result)
        }
      },(err) => {
        reject(err)
      })
    }
  })
}

手写一个Promise.race方法

// 手写一个Promise.race方法
function myPromiseRace(promises) {
  // 返回一个新的promise对象
  return new myPromise((resolve,reject) => {
    for (let i = 0; i < promises.length; i++) {
      myPromise.resolve(promises[i]).then((data) => {
        resolve(data)
      },(err) => {
        reject(err)
      })
    }
  })
}

手写一个Promise.allSettled方法

// 手写一个Promise.allSettled方法
function myPromiseAllSettled(promises) {
  // 返回一个新的promise对象
  return new myPromise((resolve,reject) => {
    let count = 0
    let result = []
    for (let i = 0; i < promises.length; i++) {
      myPromise.resolve(promises[i]).then((data) => {
        count++
        result[i] = {
          status: 'fulfilled',
          value: data
        }
        if (count === promises.length) {
          resolve(result)
        }
      },(err) => {
        count++
        result[i] = {
          status: 'rejected',
          reason: err
        }
        if (count === promises.length) {
          resolve(result)
        }
      })
    }
  })
}

手写一个Promise.any方法

// 手写一个Promise.any方法
function myPromiseAny(promises) {
  // 返回一个新的promise对象
  return new myPromise((resolve,reject) => {
    let count = 0
    let result = []
    for (let i = 0; i < promises.length; i++) {
      myPromise.resolve(promises[i]).then((data) => {
        resolve(data)
      },(err) => {
        count++
        result[i] = err
        if (count === promises.length) {
          reject(new AggregateError(result))
        }
      })
    }
  })
}

手写一个Promise.anySettled方法

// 手写一个Promise.anySettled方法
function myPromiseAnySettled(promises) {
  // 返回一个新的promise对象
  return new myPromise((resolve,reject) => {
    let count = 0
    let result = []
    for (let i = 0; i < promises.length; i++) {
      myPromise.resolve(promises[i]).then((data) => {
        count++
        result[i] = {
          status: 'fulfilled',
          value: data
        }
        if (count === promises.length) {
          resolve(result)
        }
      },(err) => {
        count++
        result[i] = {
          status:'rejected',
          reason: err
        }
        if (count === promises.length) {
          resolve(result)
        }
      })
    }
  })
}

手写一个Promise.finally方法

// 手写一个Promise.finally方法
function myPromiseFinally(onFinally) {
  return this.then((value) => {
    onFinally()
    return value
  },(err) => {
    onFinally()
    throw err
  })
}

手写一个Promise.resolve方法

// 手写一个Promise.resolve方法
function myPromiseResolve(value) {
  // 返回一个新的promise对象
  return new myPromise((resolve,reject) => {
    if (value instanceof myPromise) {
      value.then(resolve,reject)
    } else {
      resolve(value)
    }
  })
}

手写一个Promise.reject方法

// 手写一个Promise.reject方法
function myPromiseReject(reason) {
  // 返回一个新的promise对象
  return new myPromise((resolve,reject) => {
    reject(reason)
  })
}

手写一个Promise.catch方法

// 手写一个Promise.catch方法
function myPromiseCatch(onRejected) {
  return this.then(null,onRejected)
}