call apply bind的作用和区别,以及手写实现

这篇博客深入探讨了JavaScript中call、apply和bind这三个函数方法,它们都能改变函数内部的this指向。call和apply在调用函数时立即执行,call接受多个参数依次传入,apply的第二个参数为包含参数的数组。bind则返回一个修改了this的新函数,不立即执行。文中还提供了这三个方法的手动实现,并通过实例展示了它们的用法。
摘要由CSDN通过智能技术生成

相同点

都可以改变函数内部的this指向
接收的第一个参数都是this要指向的对象
都可以利用后续参数传参
不同点
call和bind传参相同,多个参数依次传入的
apply只有两个参数,第二个参数为数组
call和apply都是对函数进行直接调用,而bind方法不会立即调用函数,而是返回一个修改this后的函数

call的用法

fn.call(thisArg, arg1, arg2, arg3, ...)

调用fn.call时会将fn中的this指向修改为传入的第一个参数thisArg;将后面的参数传入给fn,并立即执行函数fn。

let obj = {
  name : '张三',
  age : 25,
  sayHello : function (hobby, address) {
    console.log(`我是${this.name},今年${this.age}岁,我的爱好是${hobby},我的家乡是${address}`)
  }
}
 obj.sayHello('打篮球','杭州')  //我是张三,今年25岁,我的爱好是打篮球,我的家乡是杭州


let obj1 = {
  name : '李四',
  age : 20,
}
 obj.sayHello.call(obj1,'画画','合肥')  //我是李四,今年20岁,我的爱好是画画,我的家乡是合肥

apply的用法

apply(thisArg, [argsArr])

fn.apply的作用和call相同:修改this指向,并立即执行fn。区别在于传参形式不同,apply接受两个参数,第一个参数是要指向的this对象,第二个参数是一个数组,数组里面的元素会被展开传入fn,作为fn的参数。

let obj = {
  name : '张三',
  age : 25,
  sayHello : function (hobby, address) {
    console.log(`我是${this.name},今年${this.age}岁,我的爱好是${hobby},我的家乡是${address}`)
  }
}
 obj.sayHello('打篮球','杭州')  //我是张三,今年25岁,我的爱好是打篮球,我的家乡是杭州
 
let obj2 = {
  name : '王五',
  age : 10,
}
obj.sayHello.apply(obj2,['跳舞','合肥']) //我是王五,今年10岁,我的爱好是跳舞,我的家乡是合肥

bind的用法

bind(thisArg, arg1, arg2, arg3, ...)

fn.bind的作用是只修改this指向,但不会立即执行fn;会返回一个修改了this指向后的fn。需要调用才会执行:bind(thisArg, arg1, arg2, arg3, ...)()。bind的传参和call相同。

let obj = {
  name : '张三',
  age : 25,
  sayHello : function (hobby, address) {
    console.log(`我是${this.name},今年${this.age}岁,我的爱好是${hobby},我的家乡是${address}`)
  }
}
obj.sayHello('打篮球','杭州')  //我是张三,今年25岁,我的爱好是打篮球,我的家乡是杭州


let obj3 = {
  name : '陈六',
  age : 60,
}
// obj.sayHello.bind(obj3,'唱歌','合肥')  //无输出
obj.sayHello.bind(obj3,'唱歌','合肥')()  //我是王五,今年10岁,我的爱好是唱歌,我的家乡是合肥

手写call

Function.prototype.myCall = function (obj) {

obj = obj || window; //当传入的参数为 null/undefined 时指向window

obj.fn = this;  //相当于在obj对象添加fn方法  // this是指调用myCall的函数

let args = [...arguments].slice(1)
let result = obj.fn(...args);

delete obj.fn  //原来的obj中没有fn方法  所以要删除

return result
}



//测试
function Fn(a,b,c,d) {
  console.log(this.name,a,b,c,d)
}

const o = {
  name : '张三',
}

Fn.myCall(o,1,2,3,4,5) //张三 1 2 3 4

手写apply

Function.prototype.myApply = function (obj) {

  obj = obj || window

  obj.fn = this;

  let result;

  if (arguments[1]){
    result = obj.fn(...arguments[1])
  }else{
    result = obj.fn()
  }

  delete obj.fn;
  return result;
}


//测试
function Fn(a,b,c,d) {
  console.log(this.name,a,b,c,d)
}

const o = {
  name : '张三',
}
Fn.myApply(o,[1,2,3,4])  //张三 1 2 3 4

手写bind

Function.prototype.myBind = function (obj) {

  let  that = this; //this指向调用myBind的函数

  let args = [...arguments].slice(1)

  return function () {  //bind返回的是函数
    //这里面的this指向window
    let arg = [...args, ...arguments] //这里面的arguments为里面函数的arguments
    return that.apply(obj,arg)
  }
}


function Fn(a,b,c,d) {
  console.log(this.name,a,b,c,d)
}

const o = {
  name : '张三',
}
Fn.myBind(o,1,2,)(3,4) //张三 1 2 3 4

call、apply、bind手写

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值