xianzao / xianzao-interview

前端 每日一道面试题
64 stars 4 forks source link

【2022.11.29】手写 call、apply、bind #7

Open xianzao opened 1 year ago

xianzao commented 1 year ago

手写 call、apply、bind

xianzao commented 1 year ago

1. 回顾call、apply、bind的用法

function sayHelloTo (to) {
    console.log(`${this.name} say hello to ${to}`)
}

var Jerry = {
  name: 'Jerry'
}
sayHelloTo.call(Jerry, 'Tom')
//Jerry say hello to Tom.

var Foo = {
  name: 'Foo'
}
sayHelloTo.apply(Foo, ['Bar'])
//Foo say hello to Bar.

var XYZ = {
  name: 'XYZ'
}
var say = sayHelloTo.bind(XYZ)
say('ABC')

2. 手写call

做一个myCall,来模拟call。

Function.prototype.myCall = function(context, ...args) {
  // 判断是否是undefined和null
  if (typeof context === 'undefined' || context === null) {
    context = window
  }
  let fnSymbol = Symbol()
  context[fnSymbol] = this
  let fn = context[fnSymbol] (...args)
  delete context[fnSymbol] 
  return fn
}

核心思路是:

为传入的context扩展一个属性,将原函数指向这个属性 将context之外的所有参数全部传递给这个新属性,并将运行结果返回。

3. 手写apply

Function.prototype.myApply = function(context, args) {
  // 判断是否是undefined和null
  if (typeof context === 'undefined' || context === null) {
    context = window
  }
  let fnSymbol = Symbol()
  context[fnSymbol] = this
  let fn = context[fnSymbol] (...args)
  return fn
}

思路和call是一样的只是传参不同方式而已

4. 手写bind方法

Function.prototype.myBind = function(context) {
// 判断是否是undefined和null
    if (typeof context === "undefined" || context === null) {
        context = window;
    }
    self = this;
    return function(...args) {
        return self.apply(context, args);
    }
}