在JavaScript中,call
、apply
和bind
都是用来改变函数执行上下文的方法,它们都能够显式地指定函数运行时的 this
值。
call
call
方法用于调用一个函数,其语法如下:
fun.call(thisArg, arg1, arg2, ...)
fun
: 要调用的函数。thisArg
: 被调用时作为this
的对象。arg1
,arg2
, …: 函数调用时传递的参数。
call
方法会将 thisArg
指定为函数的执行上下文,也就是函数内部的 this
值。可以通过传递额外的参数来调用函数。
示例:
const obj = {
name: 'Alice',
sayHello() {
console.log(`Hello, ${
this.name}!`)
}
}
const obj2 = {
name: 'Bob'
}
obj.sayHello() // Hello, Alice!
obj.sayHello.call(obj2) // Hello, Bob!
call手写模拟
Function.prototype.myCall = function (context,...args) {
//注意:context是要绑定的指向;this是调用myCall的函数;
//也就是将this的this指向context
let result = null;
// 判断 context 是否传入,如果没有传就设置为 window
context = context || window;
context.fn = this;
// 执行要被调用的方法
result = context.fn(...args);
// 删除手动增加的属性方法
delete context.fn;
// 将执行结果返回
return result;
};
apply
apply
方法与 call
方法类似,它也是用来调用函数并指定函数执行上下文的,但是它传递参数的方式不同,它的语法如下:
fun.apply(thisArg, [argsArray])
fun
: 要调用的函数。thisArg
: 被调用时作为this
的对象。argsArray
: 一个数组或类数组对象,其中的元素将作为单独的参数传递给函数。
apply
方法会将 thisArg
指定为函数的执行上下文,并将 argsArray
数组中的元素作为函数调用时的参数。
示例:
const numbers = [5, 6, 2, 3, 7]
const maxNumber = Math.max.apply(null, numbers)
console.log(maxNumber) // 7
apply手写模拟
Function.prototype.myApply = function (context,args) {
//注意:context是要绑定的指向;this是调用myApply的函数;
//也就是将this的this指向context
let result = null;
// 判断 context 是否传入,如果没有传就设置为 window
context = context || window;
context.fn = this;
// 执行要被调用的方法
result = context.fn(...args);
// 删除手动增加的属性方法
delete context.fn;
// 将执行结果返回
return result;
};
bind
bind
方法与 call
和 apply
方法有所不同,它不是立即调用函数,而是创建一个新的函数,并将 this
值绑定到指定的对象上。它的语法如下:
fun.bind(thisArg, arg1, arg2, ...)
fun
: 要绑定this
的函数。thisArg
: 被绑定时作为this
的对象。arg1
,arg2
, …: 被绑定时传递给函数的参数。
bind
方法不会立即执行函数,而是返回一个新的函数,这个新的函数的 this
值被永久绑定在 thisArg
对象上。绑定后的函数可以像原函数一样被调用,并且可以传递参数。注意,当调用绑定函数时,会将绑定函数中的参数和传递的参数合并,传递给原函数。
function greeting() {
console.log('Hello, ' + this.name + '!')
}
const person = {
name: 'John'
}
const greet = greeting.bind(person)
greet() // 输出:Hello, John!
在上面的例子中,bind()
方法将person
对象绑定到greeting()
函数的this
关键字上,并返回一个新的函数greet()
。调用greet()
函数时,执行该函数并输出Hello, John!
。注意,bind()
方法并不会立即执行函数,而是返回一个新的函数。
bind手写
Function.prototype.myBind = function (context,...args) {
//注意:this是调用myBind的函数,context是期望绑定的指向
//也就是绑定this的this指向context
let that = this
//返回一个函数
return function Fn() {
//这个被返回的函数一旦被调用,则调用真正的函数,并绑定其this指向
let result = null
context = context || window;
//这个函数中的this指向Fn()的调用者
//所以,要用that拿到myBind的this
context.fn = that;
result = context.fn(...args);
//鲁棒: result = context.fn(...[...args,...arguments]);
delete context.fn;
return result;
};
};