美文网首页前端面试题
深入理解bind/call/apply以及手写

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

作者: 前端_酒館 | 来源:发表于2021-05-21 14:28 被阅读0次

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的输出结果

相关文章

网友评论

    本文标题:深入理解bind/call/apply以及手写

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