🐸简单明了一文教你手写bind、call、apply
一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第3天,点击查看活动详情。
修改JS中this的指向是面试中老生常谈的问题了,实际开发中我们也会遇到他们的使用场景,今天带大家手写这三个方法。
1. 使用方法
首先创建两个对象:
const ObjA = {
name: 'ObjA',
say(words: string = 'Hello', words2: string = '') {
console.log(`${this.name} 说:${words}${words2}`)
}
}
const ObjB = {
name: 'ObjB',
say(words: string = 'Hello', words2: string = '') {
console.log(`${this.name} 说:${words}${words2}`)
}
}
ObjA.say()
ObjB.say()
这时候打印出来的肯定就是他们各自的打印效果:
ObjA 说:Hello
ObjB 说:Hello
1.1 bind 方法
会修改this的指向,但是不会立即执行,原函数所需要的参数在调用时传入即可。
// this指向ObjA
ObjB.say.bind(ObjA)()
ObjB.say.bind(ObjA)('Hello World', '!')
输出:
ObjA 说:Hello
ObjA 说:Hello World!
1.2 call 方法
会修改this的指向,会立即执行,原函数所需要的参数在第2、3、...(以此类推)位置。
ObjB.say.call(ObjA)
ObjB.say.call(ObjA, 'Hello World', '!')
输出:
ObjA 说:Hello
ObjA 说:Hello World!
1.3 apply 方法
会修改this的指向,会立即执行,原函数所需要的参数需要放进一个数组里面,然后放在第二个位置。
ObjB.say.apply(ObjA)
ObjB.say.apply(ObjA, ['Hello World', '!'])
输出:
ObjA 说:Hello
ObjA 说:Hello World!
2. 手写实现
2.1 手写bind
Function.prototype.myBind = function(context, ...args) {
context = (context === undefined || context === null) ? window : context
let self = this
return function(...args2) {
context._Fn = self
let result = context._Fn(...[...args, ...args2])
delete context._Fn
return result
}
}
- 首先判空,处理传入的对象为null或者undefined
- 先保存当前调用函数的this
- 隐式绑定,当前函数的this指向了context
- 因为bind不会立即执行,所以要返回一个函数result
2.2 手写call
call方法和bind方法唯一不同就是,bind不会立即执行,call是立即执行,因此我们不需要创建一个新的函数去返回。
Function.prototype.myCall = function(context, ...args) {
context = (context === undefined || context === null) ? window : context
context._Fn = this
let result = context._Fn(...args)
delete context._Fn
return result
}
- 判空,处理传入的对象为null或者undefined
- 隐式绑定,当前函数的this指向了context
- 直接返回result
2.2 手写apply
apply方法和call方法差不多,只不过是apply用一个数组来接受其他参数。
// 第二个参数无需解构,因为他是一个数组
Function.prototype.myApply = function(context, args) {
context = (context === undefined || context === null) ? window : context
context._Fn = this
let result = context._Fn(...args)
delete context._Fn
return result
}
- 判空,处理传入的对象为null或者undefined
- 隐式绑定,当前函数的this指向了context
- 直接返回result
上面只是简单实现了几种改变this的方法,主要是提供一个思路,大家后面也可以想想如何解决一些复杂的改变this指向情况。