天天看点

深入理解bind/call/apply以及手写

bind/call/apply都是用来重新定义(改变)函数内部的this指向。

例子: 菜鸟的例子更加清晰

var year = 2021
function getDate(month, day) {
	return this.year + '-' + month + '-' + day
}

let obj = {year: 2022}
getDate.call(null, 3, 8)    //2021-3-8
getDate.call(obj, 3, 8)     //2022-3-8
getDate.apply(obj, [6, 8])  //2022-6-8
getDate.bind(obj, 3, 8)()     //2022-3-8
           

区别:

  • call 的参数是直接放进去的,第二第三第 n 个参数全都用逗号分隔,直接放到后面getDate.call(obj, … ,‘string’/number/object/fun…)
  • apply所有参数都必须放在一个数组里面传进去 getDate.call(obj, [‘string’/number/object/fun…])
  • bind除了返回是函数以外,它 的参数和call一样

实现bind/call/apply

  • bind
Function.prototype.bind = function(context, ...args1) {
  context = (context === undefined || context === null) ? window : context
	let _this = this
  return function(...args2) {
  	context.__fn = _this
    let result = context.__fn(...[...args1, ...args2])
    delete context.__fn
    return result
  }
}
           
  • call
Function.prototype.call = function(context, ...args) {
  context = (context === undefined || context === null) ? window : context
	context.__fn = this
  let result = context.__fn(...args)
  delete context.__fn
  return result
}
           
  • apply
Function.prototype.apply = function(context, args) {
  context = (context === undefined || context === null) ? window : context
	context.__fn = this
  let result = context.__fn(...args)
  delete context.__fn
  return result
}
           

调用手写的bind/call/apply: apply和call除了入参不一样,剩下的都一样

let P = {name: '李三'}
function fun(...arg){
  console.log(this.name + '真', ...arg);
}
fun.bind(P, '试试?', '试试就试试')('2222'); //李三真 试试? 试试就试试 2222
fun.bind(P, '试试?', '试试就试试')(); //李三真 试试? 试试就试试
fun.call(P, '试试?', '试试就试试'); //李三真 试试? 试试就试试 
fun.apply(P, ['试试?', '试试就试试']); //李三真 试试? 试试就试试
           
深入理解bind/call/apply以及手写

继续阅读