关于 JavaScript 中 this 指向的理解

我们在写前端页面的时候,编写JavaScript代码的时候经常会用到this关键字,比如绑定事件等等,但是JavaScript中的this指向问题一直都是比较让人头疼的问题,特别是对于初学者来讲,本来认为代码没有什么问题,结果运行出来不尽人意,而且还要花大量时间来调试找到问题所在。以下内容是根据自己所理解进行分享,有什么不对的地方希望大家指出,并一起讨论,一起进步。

首先我们要明白,this 是在代码执行过程中才会对其进行赋值,这也是 this 指向复杂的原因之一

1. 默认绑定规则

在 JavaScript 中 this 默认绑定全局变量,例如在全局变量中打印 this 就会显示 window 对象

console.log(this)	// window 对象
console.log(this === window)	// true  这也表示在全局范围内this 默认指向 window 对象

这一点很好理解,不用多讲

2. 隐式绑定规则

总的来讲,就是谁调用就指向谁

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

// 这里打印出的还是 window 对象,因为 abc() 等同于 window.abc();
// 还有就是当函数独立调用的时候,就是不借助其他自身调用时,this 指向的也是 window

这也很好理解,再来换一个例子

let a = 0;
let obj = {
	a:2,
	fn:function(){
		console.log(this);	// obj
		function test(){
			console.log(this)	// ?
		}
		test();
	}
}
obj.fn();
// 通过对象的属性的方式来调用方法时,this 就会指向对象,

但是在对象中函数中再定义一个函数时,这个时候 this 指向的会是什么呢?
回到第一点所讲过的,当函数不借助其它,通过自己来调用时,this 默认指向的是 window ,所以在上面的那个例子 第二个 this 指向的就是 window

同理,立即执行的函数中的 this 也为 window

(function(){
	console.log(this) 	// window
})()

再来看闭包中的 this

let obj = {
	fn:function(){
		return function(){
			console.log(this)
		}
	}
}

obj.fn()()  // window

可能这里就会有疑问了,这里是用了 obj 中的属性来进行调用的,但是为什么还是输出的是 window 对象呢,因为 obj.fn() 先执行时,返回的是 test 方法的引用(也可以理解为指针),通过这个引用调用 test 方法,就等同于 test() 这又回到了第一点中的函数独立调用时,this 默认指向的是 window

再来个例子(隐式丢失)

var a = 0;
function foo(){
	console.log(this);
}
let obj = {
	a:2,
	foo:foo
}
obj.foo(); 	// 这里没有疑问,打印的 obj

// 隐式丢失
let fn = obj.foo;
fn();	// 这里打印出来的为 window

这个例子有一个专有名词叫做隐式丢失,我个人理解和上一个例子中的闭包中的 this 很相像,通过函数的引用来调用函数,就会丢失对象,的引用,所以叫做隐式丢失。这里还能理解为函数的独立调用,也是指向的 window。

函数传参之间的 this 指向(参数赋值)

let a = 0;
function foo(){
	console.log(this)	// window
}
function bar(fn){
	fn();
}
let obj = {
	a:2,
	foo:foo,
}
bar(obj.foo)

这个例子中,通过对象中的属性来进行传递参数,最终打印出来的window对象,这里可以理解函数在传递参数的时候只是传递了函数的引用,也就是说只是传递了函数的指针,并没有传递这个函数是通过哪个对象来得到了,所以最终打印出来的也是 window 对象

3. 显示绑定:call,apply,bind

通过这三个方法对函数中的 this 进行改变,在 javascript 面向对象中起着很关键的作用,知识比较多,这里就不细讲了。可以直接看 API

4. new 绑定

只有是在 构造函数时,才会用到 new 绑定。是将实例化的对象绑定到 this

function Person(){
	age:18;
	// return 1;
	// return {}; 
}
let person = new Person();
console.log(this)

这里需要注意的是返回值的问题,当返回值不是一个对象的时候,通过new来赋值的就是实例化对象本身,但是如果手动添加的返回值是一个对象,那么这个对象就会赋值给 person (实际开发过程中极少用到)

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_CX_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值