bind、call、apply 区别

JS this指向与call、apply、bind
本文详细解析了JavaScript中this指向的问题,并通过对比call、apply与bind的使用方式,阐述了它们如何改变函数执行上下文。同时,提供了实现这些方法的代码示例。
首先说下前两者的区别。

call 和 apply 都是为了解决改变 this 的指向。作用都是相同的,只是传参的方式不同。 除了第一个参数外,call 可以接收一个参数列表,apply 只接受一个参数数组。

let a = {	
    value: 1	
}	
function getValue(name, age) {	
    console.log(name)	
    console.log(age)	
    console.log(this.value)	
}	
getValue.call(a, 'yck', '24')	
getValue.apply(a, ['yck', '24'])

bind 和其他两个方法作用也是一致的,只是该方法会返回一个函数。并且我们可以通过 bind 实现柯里化。 如何实现一个 bind 函数 对于实现以下几个函数,可以从几个方面思考

不传入第一个参数,那么默认为 window 改变了 this 指向,让新的对象可以执行该函数。那么思路是否可以变成给新的对象添加一个函数,然后在执行完以后删除?

Function.prototype.myBind = function (context) {	
  if (typeof this !== 'function') {	
    throw new TypeError('Error')	
  }	
  var _this = this	
  var args = [...arguments].slice(1)	
  // 返回一个函数	
  return function F() {	
    // 因为返回了一个函数,我们可以 new F(),所以需要判断	
    if (this instanceof F) {	
      return new _this(...args, ...arguments)	
    }	
    return _this.apply(context, args.concat(...arguments))	
  }	
}
如何实现一个 call 函数
Function.prototype.myCall = function (context) {	
  var context = context || window	
  // 给 context 添加一个属性	
  // getValue.call(a, 'yck', '24') => a.fn = getValue	
  context.fn = this	
  // 将 context 后面的参数取出来	
  var args = [...arguments].slice(1)	
  // getValue.call(a, 'yck', '24') => a.fn('yck', '24')	
  var result = context.fn(...args)	
  // 删除 fn	
  delete context.fn	
  return result	
}
如何实现一个 apply 函数
Function.prototype.myApply = function (context) {	
  var context = context || window	
  context.fn = this	
	
  var result	
  // 需要判断是否存储第二个参数	
  // 如果存在,就将第二个参数展开	
  if (arguments[1]) {	
    result = context.fn(...arguments[1])	
  } else {	
    result = context.fn()	
  }	
	
  delete context.fn	
  return result	
}

最后给大家分享一个前端交流群,欢迎大家加入......

640?wx_fmt=jpeg
640?wx_fmt=png
640?wx_fmt=png

640?wx_fmt=jpeg

### 三者的功能与区别 在 JavaScript 中,`call`、`apply` 和 `bind` 是函数对象的三个方法,它们都用于改变函数执行时的 `this` 指向,但各自的行为和使用场景有所不同。 `call` 和 `apply` 的作用是立即调用函数,并指定其执行上下文(即 `this` 的指向),它们的主要区别在于参数传递的方式。`call` 接收的是一个参数列表,而 `apply` 接收的是一个参数数组(或类数组对象)[^3]。 ```javascript function greet(school, grade) { console.log(`${this.name} 在 ${school} 上 ${grade}`); } const person = { name: 'Alice' }; greet.call(person, '清华大学', '大一'); // Alice 在 清华大学 上 大一 greet.apply(person, ['北京大学', '研二']); // Alice 在 北京大学 上 研二 ``` `bind` 不会立即执行函数,而是返回一个新的函数,该函数的 `this` 被绑定到指定的对象。这个新函数可以在之后被调用,并且可以传递额外的参数。这种特性使得 `bind` 特别适用于事件处理或延迟执行等场景[^4]。 ```javascript const greetPerson = greet.bind(person, '复旦大学'); greetPerson('高三'); // Alice 在 复旦大学 上 高三 ``` ### 参数传递方式的差异 `call` 方法的语法为 `func.call(thisArg, arg1, arg2, ...)`,它允许将多个参数作为列表传入函数。而 `apply` 的语法为 `func.apply(thisArg, [argsArray])`,它接受一个数组或类数组对象作为参数集合[^1]。 例如,如果有一个函数 `sum(a, b)`,并希望使用 `call` 或 `apply` 来调用它,可以分别如下: ```javascript function sum(a, b) { return a + b; } const context = {}; console.log(sum.call(context, 3, 5)); // 输出 8 console.log(sum.apply(context, [3, 5])); // 输出 8 ``` ### 执行时机的不同 `call` 和 `apply` 都是立即执行函数,因此它们适用于需要在特定上下文中即时调用函数的场景。相比之下,`bind` 返回的是一个新函数,不会立即执行,而是等待后续调用[^2]。 ```javascript function logThis() { console.log(this); } const obj = { id: 123 }; const boundLogThis = logThis.bind(obj); boundLogThis(); // 输出 { id: 123 } ``` ### 使用场景与适用性 - **`call`** 更适用于需要显式指定上下文并传入多个独立参数的函数调用。 - **`apply`** 适用于参数以数组形式存在的场景,例如在数组的 `reduce`、`map` 等方法中使用。 - **`bind`** 适用于需要将函数作为回调传递,同时确保其上下文不丢失的情况,例如事件监听器、定时器回调等[^4]。 ```javascript const numbers = [5, 10, 15]; const max = Math.max.apply(null, numbers); // 15 const button = document.getElementById('myButton'); button.addEventListener('click', logThis.bind({ id: 456 })); // 点击时输出 { id: 456 } ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值