【JavaScript】常见的隐式改变this指向的几种错误

前言:this是在函数被调用时发生绑定的,它指向什么完全取决于函数在哪里被调用。(也就是说,this的指向不是函数被创建时绑定,而是被怎么样的方式调用时绑定的)。可以看看我以前写的【this的指向问题】。

 

错误一:改变函数引用

var name = 'window';

var obj = {
	name: 'obj',
	show: function(){
		console.log(this.name);	
	}	
}

var newShow = obj.show;
newShow();

输出结果:this指向了window对象了

这时候执行newShow,输出的是window,而不是obj,这里其实涉及到的对象的引用问题。在obj对象里

show: function(){}, 这是函数对象的引用。后面var newShow = obj.show;这时也把函数对象的引用指向了newShow。相当于

var newShow = function(){
	console.log(this.name);	
}	

 

错误二:函数传参

var name = 'window';

var obj = {
	name: 'obj',
	show: function(){
		console.log(this.name);	
	}	
}

function trigger(fn){
	fn();	
}
trigger(obj.show);

输出结果:this指向了window对象了

这里把obj.show通过传参的方式,传给其他函数中调用,其实这时候也发生了,函数对象的引用改变。

相当于

function trigger(){
	var fn = obj.show;	
	fn();
}

 

错误三:定时器传参

var name = 'window';

var obj = {
	name: 'obj',
	show: function(){
		console.log(this.name);	
	}	
}

setTimeout(obj.show,1000);

输出结果:this指向了window对象了

其实这里也是发生了传参,obj.show被当成了参数传给了setTimeout内置方法了。

 

错误四:DOM对象事件

var name = 'window';
var oHtml = document.documentElement;

var obj = {
	name: 'obj',
	show: function(){
		console.log(this.name);	
	}	
}

oHtml.name = 'DOM';
oHtml.onclick = obj.show;

输出结果:this指向了DOM对象

相当于

oBtn.onclick = function(){
	console.log(this.name);	
}	

还是对象函数的引用问题,还有是this的隐式绑定,this被隐式绑定给了DOM对象。

 

总结:

总的来说,导致this指向改变的原因就是有一个,那就是忽略的函数对象的引用关系(如果不清楚的朋友可以看看对象引用相关的知识点),函数对象的引用改变,也导致this(绑定)指向的改变。

如果对于this的绑定(指向)有不明白的可以看我以前写的【this的指向问题】

 

五:解决方案

①方案一

<body>
<button>点击</button>
<script>
var name = 'window';
var oBtn = document.getElementsByTagName('button')[0];

var obj = {
	name: 'obj',
	show: function(){
		console.log(this.name);	
	}	
}

//解决一
var newShow = function(){
	obj.show();	
};
newShow();     

//解决二
function trigger(fn){
	fn();	
}
trigger(function(){
	obj.show();		
});

//解决三
setTimeout(function(){
	obj.show();	
},1000);

//解决四
oBtn.onclick = function(){
	obj.show();		
};
</script>
</body>

②方案二:通过原生apply()强制改变this指向。

<body>
<button>点击</button>
<script>
var name = 'window';
var oBtn = document.getElementsByTagName('button')[0];

var obj = {
	name: 'obj',
	show: function(){
		console.log(this.name);	
	}	
}

function bind(fn,obj){
	return function(){
		return fn.apply(obj, arguments);
	};	
}

//问题一
var newShow = bind(obj.show,obj);
newShow();

//问题二
function trigger(fn){
	fn();
}
trigger(bind(obj.show,obj));

//问题三
setTimeout(bind(obj.show,obj),1000);

//问题四
oBtn.onclick = bind(obj.show,obj);

</script>
</body>

 

补充

错误六:arguments类数组改变this指向问题。

var length = 10;
function fn(){
	console.log(this.length);	
}
var obj = {
	length: 5,
	method: function(fn){
		fn();	
		arguments[0]();
	}
};

obj.method(fn,"111","222");

还是看过我前面文章的朋友应该就知道,调用obj.mehtod这里首先输出的是10,this指向全局。那argument[0]()指向的是哪里,输出的是什么?不是10,也不是5, 输出的却是3

这时候的this不是指向全局,也不是指向obj,而是指向了arguments了。

接下来我们看下以下例子:

function fn(){
	console.log(this.length);	
}
var obj1 = {
	fn:fn, 
	num1:111, 
	num2:222, 
	length:3
};
obj1.fn();

var obj2 = {
	0:fn, 
	1:111, 
	2:222, 
	length:4
};
obj2[0]();

var arr = [fn,111,222];
arr[0]();

看完就豁然开朗了吧。数组是很特殊的对象,他的索引值相当于是obj2对象中的属性值。所以说数组,类数组也会改变this指向问题。

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值