返回
函数原型方法call/apply/bind源码实现剖析
前端
2023-09-14 01:41:41
概述
在 JavaScript 中,函数是第一等公民,这意味着函数可以被存储在变量中、传递给其他函数作为参数,甚至可以作为返回值。函数的 this
指向当前函数的调用对象,通常是全局对象或调用函数的对象。然而,有时候我们需要改变函数的 this
指向,以便在不同的对象上调用它。这就是函数原型方法 call
、apply
和 bind
的用武之地。
区别
这三个方法都有相同的功能,即改变函数的 this
指向,但它们在调用方式和参数上有细微的区别:
call
方法接受两个参数:第一个参数是函数要执行的this
值,第二个参数及以后的参数是传递给函数的参数。apply
方法也接受两个参数:第一个参数是函数要执行的this
值,第二个参数是一个数组,包含要传递给函数的参数。bind
方法只接受一个参数:函数要执行的this
值。它返回一个新的函数,该函数的this
值被绑定到传入的参数。
源码实现
这三个方法的源码实现都比较简单,下面是它们的代码片段:
Function.prototype.call = function(context, ...args) {
if (typeof this !== "function") {
throw new TypeError("Function.prototype.call is not callable on non-functions");
}
context = context || globalThis;
context.fn = this;
const result = context.fn(...args);
delete context.fn;
return result;
};
Function.prototype.apply = function(context, args) {
if (typeof this !== "function") {
throw new TypeError("Function.prototype.apply is not callable on non-functions");
}
context = context || globalThis;
context.fn = this;
const result = context.fn(...args);
delete context.fn;
return result;
};
Function.prototype.bind = function(context, ...args) {
if (typeof this !== "function") {
throw new TypeError("Function.prototype.bind is not callable on non-functions");
}
const bound = (...args2) => {
return this.call(context, ...args, ...args2);
};
bound.prototype = Object.create(this.prototype);
return bound;
};
用法示例
以下是一些用法示例:
// 使用 call 方法
const obj = {
name: "John Doe",
greet: function() {
console.log(`Hello, my name is ${this.name}`);
}
};
const anotherObj = {
name: "Jane Doe"
};
obj.greet.call(anotherObj); // Hello, my name is Jane Doe
// 使用 apply 方法
const numbers = [1, 2, 3, 4, 5];
const max = Math.max.apply(Math, numbers); // 5
// 使用 bind 方法
const button = document.getElementById("my-button");
button.addEventListener("click", function() {
console.log(this); // <button id="my-button">...</button>
}.bind(button));
总结
函数原型方法 call
、apply
和 bind
是改变函数执行时的 this
指向的重要手段,它们使一个函数能够被一个不同的对象调用。虽然这三个方法都有相同的功能,但在调用方式和参数上有细微的区别。掌握这些方法的用法可以帮助您更好地编写和使用 JavaScript 代码。