什么是apply,bind,call
这三个都是可以显式绑定this的
区别
| 特性 | 是否立即执行 | 参数传递方式 | 返回值 |
|---|---|---|---|
| apply | 是 | 数组传参:fn.apply(thisArg, [arg1, arg2, ...]) | 函数执行结果 |
| bind | 否 | 逐个传参(或部分预设):fn.bind(thisArg, arg1, arg2, ...) | 新函数 (永久绑定this) |
| call | 是 | 逐个传参:fn.call(thisArg, arg1, arg2, ...) | 函数执行结果 |
详细用法
- apply
function introduce(age, city) {
console.log(`I'm ${this.name}, ${age} years old, from ${city}.`)
}
const user = { name: 'Bob' }
introduce.apply(user, [25, 'Paris'])
// 输出: I'm Bob, 25 years old, from Paris.
- bind
function say(message) {
console.log(`${message}, ${this.name}!`)
}
const tom = { name: 'Tom' }
const sayToTom = say.bind(tom, 'Hi')
sayToTom() // 输出: Hi, Tom!
// 即使作为回调,this 仍被锁定
setTimeout(sayToTom, 1000) // 1秒后仍输出: Hi, Tom!
- call
function greet(greeting, punctuation) {
console.log(`${greeting}, I'm ${this.name}${punctuation}`)
}
const person = { name: 'Alice' }
greet.call(person, 'Hello', '!')
// 输出: Hello, I'm Alice!
手写
- 手写apply
function myApply(context, argsArray) {
context = context || globalThis
// 判断进来的示例是否为空,如果为空则绑定为全局
context.fn = this
// 因为这里是函数调用myApply 所以这里的this指的是函数
const result = argsArray ? context.fn(...argsArray) : context.fn()
// 传递参数并执行函数拿到执行结果
delete context.fn // 删除fn,
return result // 返回结果
}
// 测试代码
const obj = { name: 'zhangsan' }
function test(age, gender) {
console.log(this.name, age, gender)
}
test.myApply = myApply
test.myApply(obj, [20, 'male']) // zhangsan 20 male
- 手写bind
Function.prototype.myBind = function (context, ...presetArgs) {
const fn = this
return function (...callArgs) {
// 支持 new 调用(进阶)
if (new.target) {
return new fn(...presetArgs, ...callArgs)
}
return fn.apply(context, presetArgs.concat(callArgs))
}
}
- 手写call
Function.prototype.myCall = function (context, ...args) {
context = context || globalThis // 浏览器中是 window,Node 中是 global
context.fn = this // 把函数挂到 context 上
const result = context.fn(...args)
delete context.fn // 清理
return result
}