JS中this的理解

我们在编写代码的过程中经常会遇到this的指向问题,下面对this的指向做一个总结

一、THIS:

  • 1)全局上下文中的this是window;
  • 2)块级上下文中(如:判断体“{}”,循环体“{}”)中没有自己的this,它的this是继承所在上下文中的this的;
  • 3)在函数的私有上下文中,this的情况会多种多样,也是接下来我们重点研究的;

二、函数中的THIS:

THIS不是执行上下文(EC才是执行上下文),THIS是执行主体

如何理解主体呢?
如:
张三拿着加了五个鸡蛋的煎饼果子去北京大饭店吃早餐(事情本身是吃早餐,张三吃早餐,这件事情的主体是张三【THIS】,在北京饭店吃,北京饭店是事情发生所在的上下文【EC】)

重点来了,如何区分主体呢
如何区分执行主体:

  • 事件绑定:给元素的某个事件行为绑定方法,当事件行为触发,方法执行,方法中的THIS是当前元素本身(特殊:IE6~8中基于attachEvent方法实现的DOM2事件绑定,事件触发,方法中的this是window而不是元素本身)
  • 普通方法执行(包含自执行函数执行、普通函数执行、对象成员访问调取方法执行等):只需要看函数执行的时候,方法名前面是否有“点”,有“点”,“点”前面是谁this就是谁,没有“点”this就是window[非严格模式]/undefined[严格模式]
  • 构造函数执行(new XXX):构造函数体中的this是当前类的实例
  • ES6中提供了arrow function(箭头函数): 箭头函数没有自己的THIS,它的THIS是继承所在上下文中的this
  • 可以基于call/apply/binde等方式,强制手动改变函数中的this指向:这三种模式是和直接很暴力的(前三种情况在使用这三个方法的情况后,都以手动改变的为主)

下面来看看具体事例

事件绑定:

// 事件绑定 DOM0  DOM2
let body = document.body;
body.onclick = function () {	
	console.log(this);// 事件触发,方法执行,方法中的THIS是BODY
};
body.addEventListener('click', function () {
	console.log(this); //=>BODY
});
// IE6~8中的DOM2事件绑定
 box.attachEvent('onclick', function () {
	console.log(this); //=>WINDOW
}); 

普通方法执行
1)自执行函数

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

let obj = {
	fn: (function () {
		console.log(this); //=>window
		return function () {}
	})() //把自执行函数执行的返回值赋值给OBJ.FN
};

2)普通函数执行,对象成员访问

function func() {
	console.log(this);
}
let obj = {
	func: func
};
func(); //=>方法中的THIS:WINDOW
obj.func(); //=>方法中的THIS:OBJ

实列

 [].slice(); //=>数组实例基于原型链机制,找到ARRAY原型上的SLICE方法([].slice),然后再把SLICE方法执行,此时SLICE方法中的THIS是当前的空数组
 Array.prototype.slice(); //=>SLICE方法执行中的THIS:Array.prototype
 [].__proto__.slice(); //=>SLICE方法执行中的THIS:[].__proto__===Array.prototype

构造函数

function Func() {
	this.name = "F";
	console.log(this); 
	//=>构造函数体中的THIS在“构造函数执行”的模式下,是当前类的一个实例,并且THIS.XXX=XXX是给当前实例设置的私有属性
}
Func.prototype.getNum = function getNum() {
	// 而原型上的方法中的THIS不一定都是实例,主要看执行的时候,“点”前面的内容
	console.log(this);
};
let f = new Func;//{name:'F'}
f.getNum();//{name:'F'} 自己私有属性没有getNum方法,到Func.prototype中找到执行
f.__proto__.getNum();   //{getNum: ƒ, constructor: ƒ}
//this=>f.__proto__=>Func.prototype
Func.prototype.getNum(); //{getNum: ƒ, constructor: ƒ}
//this=>Func.prototype

箭头函数

let obj = {
	func: function () {
		console.log(this);
	},
	sum: () => {
		console.log(this);
	}
};
obj.func(); //=>THIS:OBJ
obj.sum(); //=>THIS是所在上下文(EC(G))中的THIS:WINDOW
obj.sum.call(obj); //=>箭头函数是没有THIS,所以哪怕强制改也没用  THIS:WINDOW
// 不建议乱用箭头函数(部分需求用箭头函数还是很方法便的)
let obj = {
	i: 0,
	// func:function(){}
	func() {
		// THIS:OBJ
		let _this = this;
		setTimeout(function () {
			// THIS:WINDOW 回调函数中的THIS一般都是WINDOW(但是有特殊情况)
			_this.i++;
			console.log(_this);
		}, 1000);
	}
};
obj.func();
let obj = {
	i: 0,
	func() {
		setTimeout(function () {
			// 基于BIND把函数中的THIS预先处理为OBJ
			this.i++;
			console.log(this);
		}.bind(this), 1000);
	}
};
obj.func();
let obj = {
	i: 0,
	func() {
		setTimeout(() => {
			// 箭头函数中没有自己的THIS,用的THIS是上下文中的THIS,也就是OBJ
			this.i++;
			console.log(this);
		}, 1000);
	}
};
obj.func(); 
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值