# Function call, apply, bind 的实现
# call
# 核心
- 将函数设为对象的属性
- 执行&删除这个函数
- 指定
this
到函数并传入给定参数执行函数 - 如果不传入参数,默认指向 window
# 实现
因为真实面试中,面试官很喜欢让你逐步深入思考,所以这时候你可以来一波反套路,先实现一个乞丐版
# 乞丐版
var foo = {
value: 1,
bind: function() {
console.log(this.value)
}
}
foo.bind() // 1
# 皇帝版
当面试官进一步询问时,你可以装作思考一波然后给出以下版本
Function.prototype.call2 = function(that = window) {
that.fn = this
const args = [...arguments].slice(1)
const result = that.fn(...args)
delete that.fn
return result
}
var foo = {
value: 1
}
function bar(name, age) {
console.log(name, age, this.value)
}
bar.call2(foo, 'Tom', 18) // 'Tom', 18, 1
# apply
apply()
实现思路和 call()
类似,只是参数形式不同。
Function.prototype.apply2 = function(that = window) {
that.fn = this
const args = arguments[1]
const result = args? that.fn(...args) : that.fn()
delete that.fn
return result
}
# bind
bind() 会创建一个新的函数。当这个新函数被调用时,bind() 的第一个参数作为它运行时的 this,之后的一序列参数将会在传递的实参前传入作为它的参数。
此外,bind
实现需要考虑实例化后对原型链的影响。
Function.prototype.bind2 = function(obj) {
if(typeof this !== 'function') throw Error('not a function')
const context = obj ?? window
const that = this
const args = [...arguments].slice(1)
const temp() {}
const resFn = function() {
return that.apply(this instanceof resFn ? this : context, [...args, ...arguments])
}
temp.prototype = this.prototype
resFn.prototype = new temp()
return resFn
}