手写 call、apply、bind

(一)call

call 的基本用法

function person () {
  console.log(this.name)
}

let me = {
  name: 'zfb'
}

person.call(me) // zfb

person.call(me) 的意思是,调用 person 这个函数,并且把 person 函数中的 this 指向 me 这个对象,call 传参数是一个一个传

function person (a, b) {
  console.log(this.name)
  console.log(a)
  console.log(b)
}

let me = {
  name: 'zfb'
}

person.call(me, 1, 2)
// zfb
// 1
// 2

call 的作用是修改 this 指向,上面 this 指向了me这个对象

(二)apply

apply 与 call 不同的是。apply 接受的参数是一个数组,即使是一个参数,也需要放进数组里面

接收的时候,一个一个接收

function person (a, b) {
  console.log(this.name)
  console.log(a)
  console.log(b)
}

let me = {
  name: 'zfb'
}

person.apply(me, [1, 2])
// zfb
// 1
// 2

(三)特殊情况

如果给call 、apply 传入的第一个参数是 undefined 或者 null,则this指向window

function person (a, b) {
  console.log(this)
  console.log(a)
  console.log(b)
}

let me = {
  name: 'zfb'
}

person.apply(undefined, [1, 2])
person.call(undefined, 1, 2)
person.apply(null, [1, 2])
person.call(null, 1, 2)

输出:

(四)bind

bind 作用也是改变this指向,但是与call、apply不同的是,call、apply 绑定之后会立即执行,但是bind 不会立即执行,需要再次调用

function person (a, b) {
  console.log(this)
  console.log(a)
  console.log(b)
}

let me = {
  name: 'zfb'
}

person.bind(me, 1, 2) // 这时候控制台什么都没发生
person.bind(me, 1 ,2)() // 手动调用
// {name: "zfb"}
// 1
// 4 

也就是说,bind返回一个新的函数,然后我们需要去调用新的函数

const newFunction = person.bind(me, 1, 2) // 这时候控制台什么都没发生
console.log(newFunction) 
// ƒ person (a, b) {
//   console.log(this)
//   console.log(a)
//   console.log(b)
// }
newFunction() // 调用新返回的函数
// {name: "zfb"}
// 1
// 4

所以传参数,可以把参数传给新的返回的函数

person.bind(me)(1, 2)
// {name: "zfb"}
// 1
// 4 

如果绑定 null 或者 undefined,同样this 指向window

person.bind(null)(1, 2)
person.bind(undefined)(1, 2)

(五)手写 call 方法 

fn.call(obj) 的本质就是 obj.fn()

let me = {
  name: 'zfb',
  person: function (a, b) {
    console.log(this)
    console.log(a)
    console.log(b)
  }
}
me.person(1, 2)

所以我们要做的就是,把绑定的函数挂载到传入的this指向的对象上

Function.prototype.call = function (obj, ...args) {
  // 如果第一个参数是 null 或者 undefined 赋值为 window
  if (obj === null || obj === undefined) {
    obj = window
  }
  // 谁调用call,this就指向谁
  obj.p = this
  // 给obj添加一个方法,把参数传进去调用 如果有返回值就返回赋值给result
  var result = obj.p(...args)
  // 添加了之后要删除
  delete obj.p
  // 返回 result 这个返回值
  return result
}

同理,apply 也是一样

Function.prototype.apply = function (obj, args) {
  // 如果第一个参数是 null 或者 undefined 赋值为 window
  if (obj === null || obj === undefined) {
    obj = window
  }
  // 谁调用call,this就指向谁
  obj.p = this
  // 给obj添加一个方法,把参数传进去调用 如果有返回值就返回赋值给result
  var result = obj.p(...args)
  // 添加了之后要删除
  delete obj.p
  // 返回 result 这个返回值
  return result
}

call 和 apply 唯一的不同点就是,接受的参数类型不用,一个是解构后的值,一个是没解构的数组

(六)bind

bind 返回的是一个新的函数

Function.prototype.bind = function (obj, ...args) { // bind 函数传参数
  // bind 返回一个新函数
  return (...arg2s) => { // 新函数传参数
    return this.call(obj, ...args, ...arg2s) // call 返回一个返回值,将返回值返回
  }
}

bind 有两种传参数方式

person.bind(me, 1, 2)() // bind 函数传参数
person.bind(me)(1, 2) // bind 返回的新函数传参数

以上就是所有的知识点啦~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值