JavaScript 中判断一个函数的 this 绑定

this 是一个很特别的关键字,被自动定义在所有函数的作用域中。this 实际上是在函数被调用时发生的绑定,它指向什么完全取决于函数在哪里被调用(这句话不适用于箭头函数,想了解箭头函数的可以前往ES6—箭头函数)。
要判断一个运行中函数的 this 绑定,就需要找到这个函数的直接调用位置。找到之后就可以应用下面这四条规则来判断 this 的绑定对象:

  1. 函数是否在 new 中调用(new 绑定)?如果是的话 this 绑定的是新创建的对象。
var obj = new fun();
  1. 函数是否通过 callapplybind(显式绑定)或者硬绑定调用?如果是的话,this 绑定的是指定的对象。
fun.apply(obj);
fun.call(obj);
fun.bind(obj)();
  1. 函数是否在某个上下文对象中调用(隐式绑定)?如果是的话,this 绑定的是那个上下文对象。
obj.fun();
  1. 如果都不是的话,使用默认绑定。如果在严格模式下,就绑定到 undefined,否则绑定到全局对象。
fun();

上面讲述的四种情况分别 this 的四种绑定规则:默认绑定、隐式绑定、显式绑定、new绑定

默认绑定:是没有应用其他绑定规则时使用的规则,通常是独立函数调用。这时 this 在非严格模式下指向的是全局对象 window,在严格模式下指向 undefined

function fun(){
	console.log(this === window);
}

fun();	//true
function fun(){
	'use strict';
	console.log(this === undefined);
}

fun();	//true

注意:对于默认绑定来说,决定 this 绑定对象的并不是调用位置是否处于严格模式,而是函数体是否处于严格模式。如果函数体处于严格模式,this 会被绑定到 undefined,否则 this 会被绑定到全局对象。

function fun(){
	console.log(this === window);
}

(function(){
	'use strict';
	fun();
})();			//true

隐式绑定:函数的调用是在某个对象上触发的,即调用位置上存在上下文对象。这时 this 会指向这个上下文对象。

var obj = {
	fun : function(){
		console.log(this === obj);
	}
};

obj.fun();	//true

对象属性引用链中只有最顶层或者说最后一层会影响调用位置。

function fun(){
	console.log(this === obj1);
}
var obj1 = {
	fun : fun
}
var obj2 = {
	obj1 : obj1
}
var obj3 = {
	obj2 : obj2
}

obj3.obj2.obj1.fun();		//true

显式绑定:使用call()apply()bind() 把指定对象绑定到 this,这种方式称为显式绑定。想了解这三个方法的可以前往apply()、call()与bind()的用法与区别

var obj = {};
function fun(){
	console.log(this === obj);
}

fun();		//false
fun.apply(obj);		//true
fun.call(obj);		//true
fun.bind(obj)();		//true

如果你传入了一个原始值(字符串类型、布尔类型或者数字类型)来当作 this 的绑定对象,这个原始值会被转换成它的对象形式(也就是 new String(..)new Boolean(..) 或者new Number(..))。这通常被称为“装箱”。

var num = 123;
function fun(){
	console.log(this instanceof Number);
	console.log(this === num);
	console.log(typeof this);
}

fun.apply(num);		//true	false	object

如果你把 null 或者 undefined 作为 this 的绑定对象传入 callapply 或者 bind,这些值在调用时会被忽略,实际应用的是默认绑定规则。也就是在非严格模式下 this 会绑定全局对象,在严格模式下指向 undefined

function fun(){
	console.log(this === window);
}

fun.apply(null);		//true
fun.apply(undefined);		//true

硬绑定是显式绑定的一个变种,是一种显式的强制绑定。

var obj1 = {};
var obj2 = {};
function fun1(){
	console.log(this === obj1);
}
function fun2(){
	fun1.apply(obj1);
}

fun2.apply(obj2);		//true

这里我们创建了函数 fun2(),并在它的内部手动调用了 fun1.apply(obj1),因此强制把 fun1this 绑定到了 obj1。无论之后如何调用函数 fun2,它总会手动在 obj1 上调用 fun1。这种绑定是一种显式的强制绑定,因此我们称之为硬绑定

new绑定:使用 new 来调用函数,会将 this 绑定到新创建的对象上面。

function fun(){
	this.age = 23;
}
var obj = new fun();

console.log(window.age);		//undefined
console.log(obj.age);		//23

使用 new 来调用函数,或者说发生构造函数调用时,会自动执行下面的操作。

  1. 创建一个新对象;
  2. 将构造函数的作用域赋给新对象(因此 this 就指向了这个新对象);
  3. 执行构造函数中的代码(为这个新对象添加属性);
  4. 返回新对象。

如果某个函数的调用位置应用了多条规则,那么将按照:new 绑定 > 显式绑定 > 隐式绑定 > 默认绑定 的优先级来决定哪条规则会生效。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值