美文网首页
JavaScript手写call、apply、bind方法

JavaScript手写call、apply、bind方法

作者: 六寸光阴丶 | 来源:发表于2020-04-06 19:15 被阅读0次

写在前面

如果本文对您有所帮助,就请点个关注吧!

获取当前环境的公共方法

let getEnv = function() {
  return this
}

一、手写call方法

1. 源码

Function.prototype.myCall = function (ctx, ...args) {
  // 设置默认的this
  ctx = arguments[0] || getEnv()
  // 若传入的对象是字符串,需要装箱
  if (ctx instanceof String) {
    ctx = new String(ctx)
  }
  // 声明一个独有的Symbol属性,防止覆盖
  const fun = Symbol('fun')
  // 为传入对象设置函数
  ctx[fun] = this
  // 执行函数并返回结果
  const result = ctx[fun](...args)
  // 删除我们设置的属性
  delete ctx[fun]
  // 返回结果
  return result
}

2. 测试

let person = {
  name: 'person1',
  say() {
    return this.name
  }
}

let person2 = {
  name: 'person2'
}

let res = person.say.myCall(person2)
console.log(res)

// 测试结果
// person2

二、手写apply方法

1. 源码

Function.prototype.myApply = function (ctx, args) {
  // 设置默认的this
  ctx = arguments[0] || getEnv()
  // 若传入的对象是字符串,需要装箱
  if (ctx instanceof String) {
    ctx = new String(ctx)
  }
  // 声明一个独有的Symbol属性,防止覆盖
  const fun = Symbol('fun')
  // 为传入对象设置函数
  ctx[fun] = this
  // 执行函数并返回结果
  let result
  if (args) {
    result = ctx[fun](...args)
  } else {
    result = ctx[fun]()
  }
  // 删除我们设置的属性
  delete ctx[fun]
  // 返回结果
  return result
}

2. 测试

let person = {
  name: 'person1',
  say(arg1, arg2) {
    return this.name + ' ' + arg1 + ' ' + arg2
  }
}

let person2 = {
  name: 'person2'
}

let res = person.say.myApply(person2, [78, 89])
console.log(res)

// 测试结果
// person2 78 89

三、手写bind方法

1. 源码

Function.prototype.myBind = function (ctx, ...args) {
  // 设置默认的this
  ctx = arguments[0] || getEnv()
  // 记录当前this
  const _this = this
  // 返回一个函数
  return function (...args2) {
    // 声明一个独有的Symbol属性,防止覆盖
    const fun = Symbol('fun')
    // 为传入对象设置函数
    ctx[fun] = _this
    // 执行函数并记录结果
    let result = args.length !== 0 ? ctx[fun](...args) : ctx[fun](...args2)
    // 删除我们设置的属性
    delete ctx[fun]
    // 返回调用结果
    return result
  }
}

2. 测试

let person = {
  name: 'person1',
  say(arg1, arg2) {
    return this.name + ' ' + arg1 + ' ' + arg2
  }
}

let person2 = {
  name: 'person2'
}

let res1 = person.say.myBind(person2, 77, 78)()
let res2 = person.say.myBind(person2)(77, 78)
console.log(res1, res2)

// 执行结果
// person2 77 78 person2 77 78

相关文章

网友评论

      本文标题:JavaScript手写call、apply、bind方法

      本文链接:https://www.haomeiwen.com/subject/wixiphtx.html