原生JavaScript实现call、apply和bind - Web前端工程师面试题讲解
给函数指定 this 值
具体实现是 apply, call 第一个参数会接受一个上下文的环境, 给这个上下文的环境添加一个你需要调用的函数 调用它并返回调用后的结果, 之后删除你之前添加的方法
apply 传入一个数组, 而 call 传入的是一个一个的参数
bind函数会返回一个新函数, 并且这个新函数的上下文环境改变了
并且在使用 bind 的时候, 可以在创建的时候传入参数, 还可以在调用的使用传入参数
具体实现的时候需要考虑 这个新函数是 直接调用 还是使用 new 的方式调用, 不同方式会有不同返回值
使用
let o = {
x: "some strings" ,
haha(){
console.log("haha");
}
}
function f(a1, a2) {
this.haha()
console.log(this.x, a1, a2);
}
f.call(o, 1, 2)
f.apply(o, [1, 2])
let o2 = f.bind(o1) // 此时的 o2 相当于 o1 对象中的 f() 函数
o2(1, 2)
// haha
// some strings 1 2
apply实现
Function.prototype.myApply = function (context, arr) {
// 可以不传
context = context || {}
arr = arr || []
// this 代表调用的函数
context.callback = this
const res = context.callback(...arr)
delete context.callback
return res
}
let a = function (a, b, c, d) {
console.log(this.name) // 123
console.log(a, b, c, d) // 1 2 3 4
return {
a, b, c, d, name: this.name
}
}
let qw = a.myApply({ name: 123 }, [1, 2, 3, 4])
let qq = a.apply({ name: 123 }, [1, 2, 3, 4])
console.log(qw)
console.log(qq)
call 实现
Function.prototype.myCall = function (context, ...args) {
var context = context || {}
context.callback = this
const res = context.callback(...args)
delete context.callback
return res
}
let a = function (a, b, c, d) {
console.log(this.name) // zzz
console.log(a, b, c, d) // 1 2 3 4
return {
a, b, c, d, name: this.name
}
}
let qq = a.myCall({ name: 'zy' }, 1, 2, 3, 4)
let qw = a.call({ name: 'zy' }, 1, 2, 3, 4)
console.log(qq)
console.log(qw)
bind
let a = function (a, b, c, d) {
console.log(this.name) // zy
console.log(a, b, c, d) // 1 2 3 4
return 123
}
Function.prototype.myBind = function (context) {
if (typeof this !== 'function') throw new Error('error')
const args = [...arguments].slice(1), f = this
return function F() {
return f.apply(this instanceof F ? this : context, args.concat(...arguments))
}
}
let qq = a.myBind({ name: 'zy' }, 1, 2)
let qw = qq(3, 4)
console.log(qw)