# 1. 实现 call

Function.prototype._call = function (thisArg, ...args) {
  // 1. 将 thisArg 转成对象类型 (防止传入的是非对象类型)
  thisArg = (thisArg !== null && thisArg !== undefined) ? Object(thisArg) : window
    
  // 2. 定义唯一 key
  const symbolFn = Symbol(+new Date) 
  // 3. 获取需要执行的函数
    Object.defineProperty(thisArg, symbolFn, { get: () => this, configurable: true })
  // 4. 调用需要被执行的函数
  const result = thisArg[symbolFn](...args)
  // 5. 删除 symbolFn 属性
  delete thisArg[symbolFn]
  
  // 6. 将结果返回出去
  return result
}
  • 测试代码
const lain = {
  name: 'lain',
  age: 16,
  friends: []
}
function foo(...newFriends) {
  console.log(newFriends) // [' 小鸟游六花 ', ' 樱岛麻衣 ', ' 伊莉雅 ']
  this.friends.push(...newFriends)
  console.log(this) // {name: 'lain', age: 16, friends: Array(3), fn: ƒ}
}
foo._call(lain, '小鸟游六花', '樱岛麻衣', '伊莉雅')

# 2. 实现 apply

Function.prototype._apply = function (thisArg, argArray = []) {
  // 1. 将 thisArg 转成对象类型 (防止传入的是非对象类型)
  thisArg = (thisArg !== undefined && thisArg !== null) ? Object(thisArg) : window
  // 2. 定义唯一 key
  const symbolFn = Symbol(+new Date)
    
  // 3. 获取需要执行的函数
  Object.defineProperty(thisArg, symbolFn, { get: () => this, configurable: true })
  // 4. 调用需要执行的函数
  const result = thisArg[symbolFn](...argArray)
  // 5. 删除 fn 属性
  delete thisArg[symbolFn]
  // 6. 将结果返回出去
  return result
}
  • 测试代码
const lain = {
  name: 'lain',
  age: 16,
  friends: []
}
function foo(...newFriends) {
  console.log(newFriends) // [' 小鸟游六花 ', ' 樱岛麻衣 ', ' 伊莉雅 ']
  this.friends.push(...newFriends)
  console.log(this) // {name: 'lain', age: 16, friends: Array(3), fn: ƒ}
}
foo._apply(lain, ['小鸟游六花','樱岛麻衣','伊莉雅'],'saber')

# 3. 实现 bind

Function.prototype._bind = function (thisArg, argArray) {
  // 1. 将 thisArg 转成对象类型 (防止传入的是非对象类型)
  thisArg = (thisArg !== undefined && thisArg !== null) ? Object(thisArg) : window
  // 2. 定义唯一 key
  const symbolFn = Symbol(+new Date)
  // 3. 获取需要执行的函数
  Object.defineProperty(thisArg, symbolFn, { get: () => this, configurable: true })
  // 4. 返回函数地址以便调用
  return (...args) => {
    const result = thisArg[symbolFn](argArray, ...args)
    // 5. 删除 fn 函数
    delete thisArg[symbolFn]
    // 6. 将结果返回出去
    return result
  }
}
  • 测试代码
const lain = {
  name: 'lain',
  age: 16,
  friends: []
}
function foo(newFriends) {
  console.log(newFriends) // [' 小鸟游六花 ', ' 樱岛麻衣 ', ' 伊莉雅 ', ' 五河琴里]
  this.friends.push(...newFriends)
  console.log(this) // {name: 'lain', age: 16, friends: Array(4), fn: ƒ}
}
foo._bind(lain, ['小鸟游六花', '樱岛麻衣', '伊莉雅'])('五河琴里')