前端面试call()、apple()、bind() 方法的手写实现记录(常见方法的实现)

手写实现call、apple、bind 方法

认识call、apple、bind 三者

  • 功能:用来改变 this 的指向
  • call() 与 apple() 类似,不同的是call包含多个参数: call(thisObj, 1 , 2, 3 …);而apple的参数是一个数组:apple(thisObj, [1, 2, 3 …])。
  • call、apple、bind的区别:call、apple 是调用后立即返回结果;bind是返回一个函数

myCall() 方法的实现

看下面一段原生call方法

var obj1 = {
  name: '假装文艺浪',
  hobby: '打篮球',
  fn: function () {
    console.log('爱好', this.hobby)
  }
}
let obj = {
  hobby: '敲代码'
}

obj1.fn()
obj1.fn.call(obj)

// 爱好 打篮球
// 爱好 敲代码

当我们使用call方法时,打印的是 “敲代码” 而不是 “打篮球”,this指向了 obj 对象中的 hobby,即改变了this的指向
接下来实现我们自己的call()方法

Function.prototype.myCall = function(context = window, ...args) {
  if (typeof this !== 'function') {
    throw new TypeError('Type Error')
  }
  // Symbol 独一无二 ES6
  const fn = Symbol('fn')
  context[fn] = this
  const res = context[fn](...args)
  delete context[fn]
  return res
}

obj1.fn()
obj1.fn.myCall(obj)

// 爱好 打篮球
// 爱好 敲代码

查看打印结果,与原生call方法无异

apple()方法的实现

原生的apple

var obj1 = {
  name: '假装文艺浪',
  hobby: '打篮球',
  fn: function (x, y) {
    console.log('爱好',this.hobby)
    console.log(x + y)
  }
}
let obj = {
  hobby: '敲代码'
}

obj1.fn(2,3)
obj1.fn.apply(obj,[1,2])
// 爱好 打篮球
// 5
// 爱好 敲代码
// 3

call与apple的不同就是参数的形式,我们的apple() 方法的实现

Function.prototype.myApple = function(context = window, args) {
  if (typeof this !== 'function') {
    throw new TypeError('Type Error')
  }
  const fn = Symbol('fn')
  context[fn] = this
  const res = context[fn](...args)
  delete context[fn]
  return res
}

obj1.fn(2,3)
obj1.fn.myApple(obj,[1,2])
// 爱好 打篮球
// 5
// 爱好 敲代码
// 3

bind()方法的实现

原生的bind()方法

function fn (x,y) {
  console.log(this.hobby)
  console.log(x + y)
}
let obj = {
  hobby: '敲代码'
}

fn(2,3)
console.log(typeof fn.bind(obj,1,2))
fn.bind(obj,1,2)()
// undefined
// 5
// function
// 敲代码
// 3

通过打印的结果可以看出,bind()方法返回的是一个函数,而不是执行结果
this指向了obj对象

下面实现我们的bind()方法,

Function.prototype.myBind = function(context, ...args) {
  // 判断是否为函数
  if (typeof this !== 'function') {
    throw new Error("Type Error");
  }
  // 保存this的值,指向函数
  var self = this;

  return function F() {
    // 考虑new的情况
    if(this instanceof F) {
      return new self(...args, ...arguments)
    }
    // 调用apply,改变this执行
    return self.apply(context, [...args, ...arguments])
  }
}
fn(2,3)
console.log(typeof fn.myBind(obj,1,2))
fn.myBind(obj,1,2)()
// undefined
// 5
// function
// 敲代码
上一篇:vue ---v-bind 高级用法


下一篇:Vuejs第二篇(Vue基础语法)