likes
comments
collection
share

你真的会用call(), apply()和bind()吗?那手写实现呢?> 在JavaScript中,`call()`,

作者站长头像
站长
· 阅读数 50

在JavaScript中,call(), apply(), 和 bind() 是三个强大的函数方法,它们主要用于调整函数调用时this关键字的指向。虽然它们的目的相似,但在实际应用中各有其独特之处。本文将探讨这些方法的使用场景、区别以及它们的一些巧妙用法。

1. call() 和 apply()

call() 方法

call() 方法接受一个参数列表,第一个参数用于指定函数执行时this的值,后续参数则按顺序传递给函数。

示例:

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

let obj = {year: 2024};
getDate.call(obj, 7, 11); // 输出: "2024-7-11"
apply() 方法

call()相似,apply()也用于设置函数执行时this的值,但它的参数以数组形式传递。

示例:

getDate.apply(obj, [7, 12]); // 输出: "2024-7-12"

适用场景:

  • 当参数数量不确定或参数来自数组时,使用apply()更为方便。

巧妙用法:

  • 结合内置函数如Math.max()Array.prototype.push(),使用apply()可以处理动态参数列表。

2. bind()

bind() 方法与call()apply()不同,它不立即执行函数,而是返回一个新的函数,这个函数在调用时会将this绑定到指定的对象。

示例:

var obj = {year: 2024};
var boundGetDate = getDate.bind(obj);
boundGetDate(7, 13); // 输出: "2024-7-13"

适用场景:

  • 当你需要创建一个带有预设this值的可复用函数时,使用bind()

bind()的限制:

  • bind()无法改变构造函数的this指向。当使用new操作符调用bind()返回的函数时,this将指向新创建的对象。但是这也让bind可以在动态传参时起到关键作用。

3. call(), apply()和bind()手写的实现

我们可以手动实现这些方法的基本逻辑,以加深理解。

call()和apply()的手写实现:

Function.prototype.myCall = function (context) {
   let obj = context || window
   obj.fn = this
   let args = []
   for (let i = 1, len = arguments.length; i < len; i++) {
       args.push(arguments[i])
   }
   const result = obj.fn(...args)
   return result
}

// test
function add(c, d) {
    return this.a + this.b + c + d;
}
const obj = { a: 1, b: 2 };
console.log(add.myCall(obj, 3, 4)); // 10  
console.log(add.myCall({ a: 3, b: 9 }, 3, 4)); // 19
console.log(add.myCall({ a: 3, b: 9 }, { xx: 1 }, 4)); // 12[object Object]4 


Function.prototype.myApply = function (object, arr) {
    let obj = object || window
    obj.fn = this
    let result
    if (!arr) {
        return obj.fn()
    }
    if (!(arr instanceof Array)) {
        throw new Error('params must be array')
    }
    result = obj.fn(...arr)
    delete obj.fn
    return result
}

// test
function add(c, d) {
    return this.a + this.b + c + d;
}
const obj = { a: 1, b: 2 };
console.log(add.myApply(obj)); // NaN
console.log(add.myApply(obj, [3, 4])); // 10 
console.log(add.myApply(obj, [1, 'abc', '2'])); // 4abc

bind()的手写实现:

Function.prototype.myBind = function(context, ...args) {
  let fn = this;
  let bound = function(...args2) {
    return fn.apply(context, args.concat(args2));
  };
  return bound;
};

4. 总结

1、call()、apply()和bind(),都可以用来改变this的指向。

2、它们三个的第一个参数都是this要指向的对象。

3、它们三个都能传参数,call()和bind()传的是参数列表,apply()传的是数组。

4、call()和apply()是直接调用,bind()返回的是函数,可以在后面需要时再调用,所以也可以在调用的时候再传入参数。

看到这里你已经是对这三个方法的用法和逻辑完全的理解了,写作不易,还望给个小赞👍支持一波!

转载自:https://juejin.cn/post/7390319475520913460
评论
请登录