判断this指向

本文总结了JavaScript中this指向的法则,包括在全局执行环境、简单函数调用、使用call、bind、apply,函数作为对象方法调用、作为构造函数调用等情况下this的指向,还提及了ECMA内确定this绑定的原生方法及步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转自:https://mp.weixin.qq.com/s/t1P18Nou1Jl1xZ9kCkzJvw

例子

<script>
			// 浏览器正常情况下
			console.log(this === window)   // true
		</script>
		<script>
			// 函数调用
			a = 10;
			function fn1() {
				console.log(this.a)
			}
			fn1()  // 10

			b = 2
			console.log(this.b)  //2

			function fn2() {
				this.b = 3
				console.log(this.b)  // 3
			}
			fn2()
		</script>
		<script>
			// 方法调用
			function test() {
				console.log(this.x)
			}
			x = 2
			var o = {}
			o.x = 1
			o.m = test
			o.m()  // 1
		</script>
		<script>
			// 构造函数调用
			x = 2
			function test() {
				this.x = 1
			}
			var o = new test()
			console.log(x)  // 2
		</script>
		<script>
			// apply调用
			x = 0
			function test() {
				console.log(this.x)
			}
			var o = {}
			o.x = 1
			o.m = test
			o.m.apply(o)  // 1
		</script>
		<script>
			// 函数 apply调用
			var zz = {};
			zz.a = 1000;
			a = 10;
			function fn1() {
				console.log(this.a)
			}
			fn1.apply(zz)  // 1000
			b = 2
			console.log(this.b)  //2
			function fn2() {
				this.b = 3
			}
			fn2.apply(zz)
			console.log(this.b)  // 2
		</script>
		<script>
			// 函数 apply调用
			var qqq =  { a:1 }
			var ttt =  { a:2 }
			var mmm =  { a:3 }
			function fq() {
				console.log(this)
			}
			fq.bind(qqq).bind(ttt).bind(mmm)() // {a: 1}
		</script>
		<script>
			// forEach
			var arr = [1,2,3,4]
			var newarr = [5,6,7,8]
			var newnewarr = [9,10,11,12]
			arr.forEach( function (e,i,a) {
						console.log(this) // newarr
					},
					newarr
				)
			arr.forEach( (e,i,a) => {
						console.log(this) // window
					},
					newarr
				)
		</script>
		<script>
			// 立即执行函数
			(function () {
					console.log(this) // window
			})()

			var o = {};
			o.x = 999;
			(function() {
					console.log(this)  // {x:999}
				}
			).apply(o);
			(() => {
					console.log(this) // window
					}
			)();
			(() => {
					console.log(this)  // window
				}
			).apply( o )
		</script>
		<script>
			'use strict'
			console.log(this === window) // true
		</script>
		<script>
			'use strict'
			var k = {
					a:1,
					b:2,
					c:3
				}
			const fn1 = function () {
				console.log(this)
			}
			fn1()
			// undefined
			fn1.apply(k)  // {a: 1, b: 2, c: 3}
			k.m = fn1
			k.m()  // {a: 1, b: 2, c: 3, m: ƒ}
		</script>
		<script>
			'use strict'
			const o ={
					a:1,
					b:2,
					c:3
				}
			const
				fn2 = () => {
					console.log(this)
				}
			fn2()  // window
			fn2.apply( o ) // window
			o.m = fn2
			o.m() // window
		</script>
		<script>
			'use strict'
			const oo = {
					d:function() {
						console.log(this)
					},
					e:()=> {
							console.log(this)
						}
				}
			const ooo = {
					a:1,
					b:2,
					c:3
				}
			oo.d()  // {d: ƒ, e: ƒ}
			oo.e()  // window
			oo.d.apply(ooo)  // {a: 1, b: 2, c: 3}
			oo.e.apply(ooo)  // window
			var xxx = oo.d
			var yyy = oo.e
			xxx()  // undefined
			yyy()  // window
		</script>
		<script>
			'use strict'
			// forEach
			var arr = [1,2,3,4]
			var newarr = [5,6,7,8]
			var newnewarr = [9,10,11,12]
			arr.forEach(function(e,i,a) {
						console.log(this) // newarr
					},
					newarr
				)
			arr.forEach( (e,i,a) => {
						console.log(this) // window
					},
					newarr
				)
		</script>

总结

上面简单列了 window 下的几种情况,但其实在node下的情况也类似。 其实法则总结起来就是下面几点:

  1. 无论是否在严格模式下,在全局执行环境中(在任何函数体外部) this 都指向全局对象。

  2. 简单函数调用, this 在一般模式下指向全局对象;严格模式下 this 默认为 ndefined 。

  3. call , bind, apply在非箭头函数下修改 this 值;箭头函数下无法修改(由于 箭头函数没有自己的this指针,通过 call() 或 apply() 方法调用一个函数时,只能传递参数),不管call , bind, apply多少次,函数的 this 永远由第一次的决定。

  4. 当函数作为对象里的方法被调用时,它们的 this 是调用该函数的对象。

  5. 如果该方法存在于一个对象的原型链上,那么this指向的是调用这个方法的对象,就像该方法在对象上一样。

  6. 当一个函数用作构造函数时(使用new关键字),它的this被绑定到正在构造的新对象。

在ECMA内, this 会调用 原生方法 ResolveThisBinding() 原生方法ResolveThisBinding使用正在运行的执行上下文的 LexicalEnvironment 确定关键字this 的绑定。 ResolveThisBinding执行以下步骤:

  1. 设置 envRec 为 GetThisEnvironment()

  2. 返回 envRec.GetThisBinding() 。

原生方法GetThisEnvironment找到当前提供关键字 this 绑定的环境记录。 GetThisEnvironment 执行以下步骤:

  1. 设置 lex 为正在运行的执行上下文的 LexicalEnvironment 。

  2. 重复以下行为: a. 设置 envRec 为 lex 的 环境记录; b. 设置 exists 为 envRec.HasThisBinding() c. 如果exists 为真,返回出 envRec d.设置 outer 为 lex 的外部环境参考值。 e. 断言: outer 不是 null f. 设置 lex为 outer

注意:步骤2中的循环必须终止,因为列表的环境总是以全局环境这个绑定。

转载自:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值