call、apply和bind

  |  

call、apply、 bind 通常用于修改this的指向,文章简述它们的区别以及实现原理

区别

  • call 接受多个参数
  • apply 只接受一个数组参数
  • bind 接受多个参数, 与 call 和 apply 不同, bind不执行宿主函数

使用

func.call(thisArg, param1, param2, ...)

func.apply(thisArg, [param1,param2,...])

func.bind(thisArg, param1, param2, ...)

// 举个例子
let a = {test: 1}
// 对象上是没有 push 方法的,采用call 改变this指向,可以借用方法
Array.prototype.push.call(a,{test2:2})
a // {test:1,0: {test2:2}}

// 很多时候也用于伪数组, 比如arguments 参数
const a = = [].slice.call(arguemnt)

call 实现

Function.prototype.myCall = function(context, ...args) {
context = context || window
// this 是当前借用的函数
context.fn = this
// 这时候 就是context调用 fn , this就是content
const res = context.fn(...args)
delete context.fn
return res
}

apply实现

实现差不多,主要在于参数

Function.prototype.myBind = function(context, ...args) {
context = context || window
context.fn = this
const res = context.fn(args)
delete context.fn
return res
}

bind 实现

bind 实现相对复杂一些,主要是因为 bind返回的函数可以当作构造函数

// 先不考虑构造函数的情况
Function.prototype.myBind = function(context, ..args) {
// func.bind this 就是 func
const self = this
// 这个时候还可能接受参数
return function(..args2) {
return self.apply(context, [...args,...args2])
}
}

如果作为构造函数, 那么 new 的时候, this的优先级是最高的,bind的this就失效了

new的过程(不考虑显式返回的情况):
1、 创建一个空的对象
2、 将this指向当前对象, 对象的原型也会 发生改变
3、 执行构造函数内部代码
4、返回对象

因此,关键在于判断 this 的指向问题

最终版实现

Function.prototype.myBind = function(context, ...args) {
// 如果调用 bind 的不是 函数,那么报错
if(typeof this !== 'function') {
throw new Error("Function.prototype.bind - what is trying to be bound is not callable")
}
const self = this

// 新起一个构造函数
const fNOP = function() {}
const fBound = function(..args2) {
return self.apply( this instanceof fNOP ? this : context,[...args,...args2])
}
// 我们直接将 fBound.prototype = this.prototype,我们直接修改 fBound.prototype 的时候,也会直接修改绑定函数的 prototype。因此在中间再插入一个原型对象
fNOP.prototype = this.prototype

// 让 fBound的原型是 fNOP的实例,
//那么根据原型链, 只要判断 this instanceof fNOP 则可判断是否是 new
fBound.prototype = new fNOP()
return fBound;
}

×

纯属好玩

扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

文章目录
  1. 1. 区别
  2. 2. 使用
  3. 3. call 实现
  4. 4. apply实现
  5. 5. bind 实现
,