手写原生方法

手写原生方法

代码实现 JavaScript 系列

手写实现 call

call 主要都做了些什么?

call() 方法使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数。

分析:

  1. 更改 this 指向
  2. 函数立刻执行
function.call(thisArg, arg1, arg2, ...)

参数:

  • thisArg

    可选的。在 function 函数运行时使用的 this 值。请注意,this可能不是该方法看到的实际值:如果这个函数处于非严格模式下,则指定为 nullundefined 时会自动替换为指向全局对象,原始值会被包装。

  • arg1, arg2, ...

    指定的参数列表。

返回值:

使用调用者提供的 this 值和参数调用该函数的返回值。若该方法没有返回值,则返回 undefined

代码实现:

Function.prototype.myCall = function (context) {
  // 判断有没有传入要绑定的对象,没有默认是window
  // 如果是基本类型的话通过Object()方法进行转换
  // 使用 var 重新定义函数局部变量  
  var context = Object(context) || window

  context.fn = this

  // 保存返回值
  let result = ''

  // 取出传递的参数 第一个参数是this, 下面是三种截取除第一个参数之外剩余参数的方法
  // 通过...展开运算符将伪数组 argument是转换伪数组,使用数组方法返回参数数组
  const args = [...arguments].slice(1)

  // 执行方法
  result = context.fn(...args)

  // 删除绑定,不删除会一直绑fn
  delete context.fn

  // 返回函数执行结果
  return result
}

//test
const a = [1, 2]
console.log(Object.prototype.toString.call(a))
console.log(Object.prototype.toString.myCall(a))

手写实现 apply

实现了call 其实也就间接实现了apply,只不过就是传递的参数不同

Function.prototype.myApply = function (context, args) {
  var context = Object(context) || window

  context.fn = this

  let result = ''

  // 判断有没有传入 args
  if (!args) {
    result = context.fn()
  } else {
    result = context.fn(...args)
  }

  delete context.fn

  return result
}

手写实现 bind

bind 特性:

  • 指定this
  • 返回一个函数
  • 传递参数并柯里化
Function.prototype.myBind = function(ctx, ...args) {
    return (...innerArgs) => this.call(ctx, ...args, ...innerArgs);
  };

手写实现 Promise

简单实现一个 Promise 类

function MyPromise(executor) {
  // 初始化 state 为等待态
  this.state = 'peding'
  // 成功的值
  this.value = undefined
  // 失败的原因
  this.reason = undefined

  let resolve = value => {
    if (this.state === 'pending') {
      // resolve调用后,state转化为成功态
      this.state = 'fulfilled'
      // 储存成功的值
      this.value = value
    }
  }
  let reject = reason => {
    // state改变,reject调用就会失败
    if (this.state === 'pending') {
      // reject调用后,state转化为失败态
      this.state = 'rejected'
      // 储存失败的原因
      this.reason = reason
    }
  }

  try {
    executor(resolve, reject)
  } catch (error) {
    reject(error)
  }
}

Promise all 方法

// Promise.all
// Promise.all 需要等到所有的 promise 的状态都变成 fulfilled 之后才 resolve, 但只要有一个 promise 失败即返回失败的结果。
MyPromise.all = function (arr) {
  return new Promise((resolve, reject) => {
    if (Array.isArray(arr)) {
      throw new Error(`argument must be a array`)
    }
    let dataArr = []
    let num = 0

    for (let i = 0; i < arr.length; i++) {
      let p = arr[i]
      p.then(data => {
        dataArr.push(data)
        num++
        if (num === arr.length) {
          return resolve(data)
        }
      }).catch(e => {
        return reject(e)
      })
    }
  })
}

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!