this指向

本文详细阐述了JavaScript中的执行机制,包括预解析、作用域链和变量对象。重点讨论了this的关键概念,在全局作用域、普通函数、箭头函数以及构造函数中的不同行为。此外,还通过示例解释了在立即执行函数、定时器回调和DOM事件绑定中this的指向问题,以及箭头函数对this的影响。
摘要由CSDN通过智能技术生成

1. 前言

1.1 浏览器中js执行机制:

词法分析、语法分析 ===> AST 含预解析的过程:变量和函数声明提升为全局对象的属性
全局执行上下文(scope chain、vo(go)、this binding(执行时才确定))入执行栈,执行
遇到函数执行语句,函数内部的变量、函数提升为该函数的ao的属性
该函数的执行上下文(scope chain、vo(go)、this binding(执行时才确定))入栈,执行,出栈,继续执行全局执行上下文的代码

2. this

MDN this

2.1 在全局作用域中

go有个window属性使得全局对象指向自己,this指向window全局对象

<script>
	// this是关键字,值是当前执行上下文(global、function 或 eval)的一个属性,在非严格模式下,总是指向一个对象
	console.log(this) 
</script>
2.2 在普通函数中

谁调用这个函数,函数中的this就指向谁,和在何处定义无关;

function foo() {
	console.log('this', this);
}
foo(); // window
2.3 箭头函数中的this

箭头函数的this和它所在作用域的this有关,即上级执行上下文的this指向谁,它内部的this就指向谁;且指向不会改变。

箭头函数不能用作构造函数,因为js构造函数实例对象时,需要改变this的指向(指向空对象),使得属性和方法在实例对象上;而箭头函数的this指向不能改变。

2.4 构造函数中的this

指向实例化对象,new关键字的作用

new四步:

  1. 申请一块内存,存放空对象
  2. 利用call方法改变构造函数内部this指向,使this指向实例化的这个空对象(属性)
  3. 把实例化对象的隐式原型指向构造函数的显示原型(方法)
  4. 如果执行结果有返回值并且是一个对象, 返回执行的结果, 否则, 返回新创建的对象。

new的实现:
手写new

1

3. 示例

3.1 立即执行函数

this指向window

(function foo() {
	console.log('IIFE', this);
})();
3.2 定时器回调函数中的this

定时器的回调函数本身是普通函数时: 无论定时器是否定义在事件绑定的普通函数内,都指向window

setTimeout(function() { 
	console.log(this);  // window
,500)
<ul class="father">
  <li class="btn">保存</li>
  <li></li>
</ul>

<script>
btn.addEventListener('click', function (e) {
	console.log('this:', this, 'e.target', e.target); // this: <ul class=​"father">​…​</ul>​ e.target <li class=​"btn">​…​</li>​

	setTimeout(function () {
		console.log('timerFunc', this); // 定时器的回调是普通函数: window
	}, 500);
});
</script>

定时器的回调函数本身是箭头函数函数时: 如果定时器是在某个函数内部注册的,this指向和它相同,如果定时器在全局作用域中,则指向window

<ul class="father">
  <li class="btn">保存</li>
  <li></li>
</ul>

<script>
btn.addEventListener('click', function (e) {
	console.log('this:', this, 'e.target', e.target); // this: <ul class=​"father">​…​</ul>​ e.target <li class=​"btn">​…​</li>​

	setTimeout(()=> {
		console.log('timerFunc', this); // 定时器的箭头函数: <ul class=​"father">​…​</ul>​
	}, 500);
});
</script>

怎么感觉这么诡异?这里只是确定了是谁调用定时器的回调?

3.3 DOM事件绑定中的this

回调函数是普通函数时:

this指向绑定的事件源(节点),和到底谁触发了无关(事件委托:给父元素绑定点击事件,点击子元素,因为事件冒泡,仍会触发父元素的点击事件执行回调;e.target是点击的子元素、this是绑定了事件的父元素)

<body>
<ul class="father">
  <li class="btn">保存</li>
  <li></li>
</ul>
<script>
  const btn = document.querySelector('.father');
  btn.addEventListener('click', function (e) {
	console.log('this:', this, 'e.target', e.target);
  });
</script>

在这里插入图片描述

回调函数是箭头函数时:

<body>
<ul class="father">
  <li class="btn">保存</li>
  <li></li>
</ul>
<script>
  const btn = document.querySelector('.father');
  btn.addEventListener('click', (e) => {
	console.log('this:', this, 'e.target', e.target); //this: window , e.target: li
  });
</script>

在这里插入图片描述

这里箭头函数内的this指向全局,是因为它的上一层作用域其实就是全局作用域,虽然这个回调的调用者是btn对象,但箭头函数的this在定义时确定,而不是调用时。

3.4 原型链中的this

对象的原型链上的方法内的this,指向实例对象本身

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值