参考对象调用方法时,函数内this的指向是这个对象本身的原理,可实现改变this的指向
const obj = {
name: 'this的指向',
getName: function () {
console.log(this)
return this.name
}
}
obj.getName()
//打印 {name: "this的指向", getName: ƒ}
实现思路:
创建一个改变this指向的方法customCall(context, a, b, c)
fn(a, b, c){
console.log(this, a, b, c)
}
要改变 fn 函数内部的 this 指向,可通过第一个参数 context 去调用 fn 方法:
context.fn() 此时 fn 函数的内部 this 的指向就是 context;
要实现 context.fn() 可调用,就需要将 fn 方法设置成为 context 的一个属性方法;
可通过原型链的方式将 fn 方法设置为 context 对象的原型方法;
具体的实现方法如下:
call方法实现:
Function.prototype.customCall = function(context, ...agrs){
if(context === null) context = globalThis;
if(typeof context !== 'Object') context = new Object(context);
const fnkey = Symbol() //保证key唯一
Object.prototype[fnkey] = this //this指向调用customCall方法的对象,此处应为fn
const res = context[fnkey](...agrs) //通过context调用fn方法
delete Object.prototype[fnkey] //防止污染
return res
}
//示例
function fn(a, b, c){
console.log(this, a, b, c)
}
fn.customCall({a:1, b:2}, 10, 20, 30)
//打印结果: {a:1, b:2} 10 20 30
apply方法实现:
Function.prototype.customApply = function(context, agrs = []){
if(context === null) context = globalThis;
if(typeof context !== 'Object') context = new Object(context);
const fnkey = Symbol()
Object.prototype[fnkey] = this
const res = context[fnkey](...agrs)
delete Object.prototype[fnkey]
return res
}
//示例
function fn(a, b, c){
console.log(this, a, b, c)
}
fn.customApply({a:1, b:2}, [10, 20, 30])
//打印结果: {a:1, b:2} 10 20 30
bind方法实现:
Function.prototype.customBind = function(context, ...bindAgrs){
return (...agrs) => {
const a = bindAgrs.concat(agrs)
return this.customApply(context, a)
}
}
//示例
function fn(a, b, c){
console.log(this, a, b, c)
}
const f1 = fn.customBind({a:1, b:2, c: 3}, 10, 20, 30)
f1()
//打印结果: {a: 1, b: 2, c: 3} 10 20 30
const f2 = fn.customBind({a:10, b:20, c: 30})
f2(1, 2, 3)
//打印结果: {a: 10, b: 20, c: 30} 1 2 3
customCall、customApply和customBind都是用于改变函数执行上下文的方法。它们的主要区别在于参数的传递方式和返回值。
customCall方法:
使用方式:function.customCall(thisArg, arg1, arg2, ...)
功能:立即调用一个函数,并将指定的对象作为函数的上下文(也就是this值)传递进去,可以传递多个参数。
使用场景:
在继承中,可以借用父类的方法。
实现借用其他对象的方法。
修改函数内部的this指向。
customApply方法:
使用方式:function.customApply(thisArg, [argsArray])
功能:立即调用一个函数,并将指定的对象作为函数的上下文(也就是this值)传递进去,以及一个数组或类数组对象作为参数。
使用场景:
传递不定数量的参数给函数。
使用已有的数组作为函数的参数。
customBind方法:
使用方式:function.customBind(thisArg, arg1, arg2, ...)
功能:创建一个新的函数,并将指定的对象作为新函数的上下文(也就是this值)传递进去,可以传递多个参数。
使用场景:
创建一个函数的预设参数,形成一个新的函数。
固定函数内部的this指向。
总结:
customCall和customApply都是立即调用函数并改变函数上下文,不同之处在于参数的传递方式。
customBind则是创建一个新的函数,并预设参数和上下文,不会立即执行。
这些方法在开发中可以用于更灵活地控制函数的执行上下文和参数传递。