深度解析javascript中的this(三)

本文深入探讨JavaScript中this的四种绑定规则——默认绑定、隐式绑定、显式绑定和new绑定的优先级。重点解析new绑定为何具有最高优先级,并通过源码分析证实这一观点。同时,讨论了new绑定和显式绑定在函数柯里化中的应用,以及在实际编程中如何利用这些知识来优化代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

      上一章我们说到,this绑定的四种规则,默认绑定,隐式绑定,显式绑定和new绑定,并且我们抛出了一个问题,如果当这几个绑定一起使用的时候,优先级又是怎样的,这一章我们将就这个问题进一步展开解释

正文

优先级

      毫无疑问,默认绑定的优先级是四条规则中最低的,所以我们可以先不考虑它。我们先来比较一下隐式绑定和显式绑定的优先级,看一下下面的例子:

function foo() {
	console.log( this.a );
}
var obj1 = {
	a: 2,
	foo: foo
};
var obj2 = {
	a: 3,
	foo: foo
};
obj1.foo(); // 2
obj2.foo(); // 3
obj1.foo.call( obj2 ); // 3
obj2.foo.call( obj1 ); // 2

      可以看到,显式绑定优先级更高,也就是说在判断时应当先考虑是否可以应用显式绑定。然后我们再看一下new绑定和隐式绑定的优先级谁更高

function foo(something) {
	this.a = something;
}
var obj1 = {
	foo: foo
};
var obj2 = {};
obj1.foo( 2 );
console.log( obj1.a ); // 2
obj1.foo.call( obj2, 3 );
console.log( obj2.a ); // 3
var bar = new obj1.foo( 4 );
console.log( obj1.a ); // 2
console.log( bar.a ); // 4

      可以看到 new 绑定比隐式绑定优先级高。最后我们只需要比较一下new绑定和显式绑定就可以了,new 和 call/apply 无法一起使用,因此无法通过 new foo.call(obj1) 来直接进行测试。但是我们可以使用上一章说的硬绑定来测试它俩的优先级,也就是bind

function foo(something) {
	this.a = something;
}
var obj1 = {};
var bar = foo.bind( obj1 );
bar( 2 );
console.log( obj1.a ); // 2
var baz = new bar(3);
console.log( obj1.a ); // 2
console.log( baz.a ); // 3

      不难看出,这里采用了new的this绑定,也就是new的this绑定优先级是在bind之前的,总结下来就是new绑定 > 显式绑定 > 隐式绑定 > 默认绑定,不过其实new的绑定优先级

从bind源码看为什么new绑定优先级更高

if (!Function.prototype.bind) {
	Function.prototype.bind = function(oThis) {
		if (typeof this !== "function") {
			// 与 ECMAScript 5 最接近的
			// 内部 IsCallable 函数
			throw new TypeError(
			"Function.prototype.bind - what is trying " +
			"to be bound is not callable"
		);
}
var aArgs = Array.prototype.slice.call( arguments, 1 ),
fToBind = this,
fNOP = function(){},
fBound = function(){
		return fToBind.apply(
			(
			this instanceof fNOP &&
			oThis ? this : oThis
			),
			aArgs.concat(
			Array.prototype.slice.call( arguments )
			);
		}
	;	
	fNOP.prototype = this.prototype;
	fBound.prototype = new fNOP();
	return fBound;
	};
}

      下面是 new 修改 this 的相关代码:

this instanceof fNOP &&
oThis ? this : oThis
// ... 以及:
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();

      简单来说,这段代码会判断硬绑定函数是否是被 new 调用,如果是的话就会使用新创建的 this 替换硬绑定的 this。所以这也是为什么new绑定的优先级在bind之上

new绑定和显式绑定在函数柯里化的应用

      那么,为什么要在 new 中使用硬绑定函数呢?直接使用普通函数不是更简单吗?之所以要在 new 中使用硬绑定函数,主要目的是预先设置函数的一些参数,这样在使用new 进行初始化时就可以只传入其余的参数。bind(…) 的功能之一就是可以把除了第一个参数(第一个参数用于绑定 this)之外的其他参数都传给下层的函数(这种技术称为“部分应用”,是“柯里化”的一种)。举例来说:

function foo(p1,p2) {
	this.val = p1 + p2;
}
// 之所以使用 null 是因为在本例中我们并不关心硬绑定的 this 是什么
// 反正使用 new 时 this 会被修改
var bar = foo.bind( null, "p1" );
var baz = new bar( "p2" );
baz.val; // p1p2

小结

      这一章我们介绍了this相关绑定的优先级关系,并且从源码层面阐述了new绑定的优先级在显式绑定之前,但是既是规则,总有例外,下一章我们将进一步分析this绑定规则之外的一些例外情况,谢谢学习
      小伙伴们今天的学习就到这里了,如果觉得本文对你有帮助的话,欢迎转发,评论,收藏,点赞!!!
      每天学习进步一点点,就是领先的开始。如果想继续提高,欢迎关注我,或者关注公众号”祯民讲前端“。大量前端技术文章,面试资料,技巧等助你更进一步!
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值