JS 之 手写call、apply、bind、函数柯里化

1.最简单的call

Function.prototype.myCall = function(thisArg, ...args) {
  // 1.获取需要被执行的函数,此时的this就是函数
  let fn = this
  // 2.对thisArg转成对象类型(防止它传入的是非对象类型)    Object(thisArg)可以把基本数据类型变成对象类型
  thisArg = thisArg !== undefined && thisArg !== null ? Object(thisArg) : window
  // 因为需要改变指向,所以赋值为一个属性
  thisArg.fn = fn
  // 3.调用需要被执行的函数
  thisArg.fn(...args)
  // 删除这个多余的属性   打印的时候这属性还在
  delete thisArg.fn
}

function foo(num1, num2) {
  console.log('foo', num1, num2, this)
}

foo.myCall(0, 1, 2, 3, 4, 5, 6, 7)

2.有一点不一样的apply

// 这里参数可以来个默认参数,防止没传参数时,解构会报错
Function.prototype.myApply = function(thisArg, args = []) {
  // 1.获取到要执行的函数
  let fn = this
  // 2.处理绑定的thisArg
  thisArg = thisArg !== null && thisArg !== undefined ? Object(thisArg) : window
  // 3.执行函数
  thisArg.fn = fn
  thisArg.fn(...args)
  delete thisArg.fn
}

function foo(num1, num2) {
  console.log('foo函数被执行', this, num1, num2)
}

foo.myApply({ name: 123 }, [1, 2, 3])

3.最后的bind

Function.prototype.myBind = function(thisArg, ...args) {
  // 这里需要使用箭头函数,谁调用了myBind,this指向谁
  // 如果用 return function(){}   调用时,this变为了window
  return (...argArray) => {
    // 1.绑定this
    let fn = this
    console.log(fn)
    // 2.判定thisArg
    thisArg =
      thisArg !== undefined && thisArg !== null ? Object(thisArg) : window

    thisArg.fn = fn
    thisArg.fn(...[...args, ...argArray])
    delete thisArg.fn
  }
}

function foo(num1, num2, num3) {
  console.log('foo被执行', this, num1, num2, num3)
}

let bar = foo.myBind('123', 1, 2)

bar(3)

4.有一点绕的柯里化

 //柯里化函数的实现
  function myCurrying(fn) {
    function curried(...args) {
      // 判断当前已经接受参数的个数是否和函数本身接受的参数个数一致
      // 若传入的参数个数大于或等于函数的参数个数,直接执行
      if (args.length >= fn.length) {
        fn.call(this, ...args)
      } else {
        //没有达到个数时,需要返回新的函数,继续接受参数
        return function (...args2) {
          //接受参数后,递归调用curried来检查参数个数   需要返回到最外层,所以return
          return curried.call(this, ...[...args, ...args2])
        }
      }
    }
    return curried
  }

  //测试函数
  function foo(x, y, z) {
    console.log(x, y, z, this)
  }

  let myCallried = myCurrying(foo)
  myCallried(1)(2)(3)

  // myCallried(1, 2)(3)
  // myCallried(1)(2, 3)

猜你喜欢

转载自blog.csdn.net/a15297701931/article/details/120350624
今日推荐