使用原生js实现自定义call、apply、bind方法改变this指向

参考对象调用方法时,函数内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则是创建一个新的函数,并预设参数和上下文,不会立即执行。

这些方法在开发中可以用于更灵活地控制函数的执行上下文和参数传递。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值