YBFACC / blog

仅记录个人学习使用
3 stars 0 forks source link

手写实现call, apply,bind #2

Open YBFACC opened 4 years ago

YBFACC commented 4 years ago

本文章的基础

  1. 原型

  2. this的使用

call

介绍

call() 提供新的 this 值给当前调用的函数/方法。你可以使用 call 来实现继承:写一个方法,然后让另外一个新的对象来继承它(而不是在新对象中再写一次这个方法)。来自MDN

使用注意

在非严格模式下,第一个参数如果为null或者undefined时,会自动替换为指向全局对象。

let apple = {
  name: 'apple',
  test: function (price, time) {
    console.log(time, this.name, price)
  }
}
let pear = {
  name: 'pear'
}
//在原型链上绑定方法
Function.prototype._call = function (context, ...args) {
  if (!context || typeof context !== 'object') {
    context = global
  }
  let say = Symbol() // 防止覆盖掉原有属性
  context[say] = this // 这里的this为需要执行的方法
  const res = context[say](...args)
  delete context[say]
  return res
}
apple.test._call(pear, 10, '2020-5-29')//2020-5-29 pear 10

apply

介绍

call()方法的作用和 apply() 方法类似,区别就是call()方法接受的是参数列表,而apply()方法接受的是一个参数数组来自MDN

let apple = {
  name: 'apple',
  test: function (price, time) {
    console.log(time, this.name, price)
  }
}
let pear = {
  name: 'pear'
}
global.name = 'window'//环境为node
apple.test.apply(null, [10, '2020-5-29'])//2020-5-29 window 10

Function.prototype._apply = function (context, args) {
  if (!context || typeof context !== 'object') {
    context = global
  }
  const key = global.Symbol() // 防止覆盖掉原有属性
  context[key] = this // 这里的this为需要执行的方法
  const result = context[key](...args)
  delete context[key]
  return result
}
apple.test._apply(null, [10, '2020-5-29'])//2020-5-29 window 10

apple.test._apply(pear, [10, '2020-5-29']) //2020-5-29 pear 10

bind

介绍

返回一个原函数的拷贝,并拥有指定的 this 值和初始参数。来自MDN

let apple = {
  name: 'apple',
  test: function (price, time) {
    console.log(time, this.name, price)
  }
}
let pear = {
  name: 'pear'
}

//借助call
Function.prototype._bind = function (context) {
  if (!context || typeof context !== 'object') {
    context = global
  }
  return (...args) => {
    this.call(context, ...args)
  }
}
let fun1 = apple.test._bind(pear)
fun1(10, '2020-5-29') //2020-5-29 pear 10
let apple = {
  name: 'apple',
  test: function (price, time) {
    console.log(time, this.name, price)
  }
}
let pear = {
  name: 'pear'
}
Function.prototype._call = function (context, ...args) {
  if (!context || typeof context !== 'object') {
    context = global
  }
  let say = Symbol() // 防止覆盖掉原有属性
  context[say] = this // 这里的this为需要执行的方法
  const res = context[say](...args)
  delete context[say]
  return res
}

//不使用原生call
Function.prototype._bind_ = function (context) {
  if (!context || typeof context !== 'object') {
    context = global
  }
  return (...args) => {
    this._call(context, ...args)
  }
}

let fun2 = apple.test._bind_(pear)
fun2(10, '2020-5-29') //2020-5-29 pear 10

参考

MDN

手写JS函数的call、apply、bind实现

手写call、apply、bind实现及详解