Javascript关键字this原理解析

Javascript中this关键字原理分析

这段时间由于在对JavaScript进行更深入的学习,在深入分析的过程中遇到了this这个关键字,于是在网上查找了很多对于this相关的博文,发现很多博客中对于this关键字的理解有误,这些错误的文章容易误导新手。为防后期出现混乱现对该this关键字进行相关简单的分析。

首先,需要知道是, 在各种版本的编程语言中,例如: JavaC++C# 等很多面向对象编程语言中对this关键字都有一个相同的意思,在一个类的方法内部使用this关键字后,当使用该类实例化一个对象时,this关键字均指向该实例化的对象实体,例如在 Java 中代码如下:

class TestObject{
	private String field = "这个是TestObject对象的field属性";
	/**
	 * 当实例对象调用此方法后,this关键字指向的即为调用者本身
	 */
	public void method() {
		System.out.println("this关键字: " + this);
		System.out.println(this.field);
	}
}

在传统的面向对象编程语言的语法中,this关键字定义在实例方法,当实例对象调用是方法后this关键字则会指向调用方实例对象。由于 Java等语言属于严格意义上的传统面向对象编程语言,this关键字有着很明确的定义和使用规则,所以在使用上并不会很难理解。
由于JavaScript并不是像Java那样有着严格的面向对象语法,且JavaScript是基于原型实现的面向对象语言,它在变量的作用域方面也不是像Java等面向对象语言那样是快级作用域,而是函数作用域,即变量的作用范围仅在函数内部。
每次手打JavaScript太麻烦,以下都用js代替JavaScript了。

这里可能解释的不对,这里的作用域与语言是否是面向对象原则上应该是不冲突的

由于js变量作用域的特殊性,在实例化对象时其变量的作用域链查找方式与传统面向对象的方式也有些区别。

首先在Java等面向对象中,如果类中定义了一个属性并设置属性的值,那么在方法中直接使用该属性时会直接调用实例对象中的属性。

我在此处的理解是: 由于传统面向对象编程语言是以块级作用域由内向外逐层寻找定义的变量,即在代码块中寻找定义的变量,如果对于的变量未找到则再向外层的代码块寻找变量,如果还未找到则再向更外层代码块处寻找直至找到最外层,如果任未找到则抛出编译错误。

由于js是函数作用域,其变量的作用域于传统面向对象编程语言不同,在寻找变量时是以函数级别进行自内向外寻找,直至寻找到最外层的全局作用域。所以在函数中的变量如果再未定义的情况下调用,此时js解释引擎则会查找嵌套该函数的外层函数,如果未找到则再往更外层寻找。

自制的原理图如下
未找到
未找到
最后仍未找到
当前函数
上级函数
上级函数
...一层一层向上找嵌套的函数
最外层的全局作用域

同理:,在任何编程语言中this关键字都保存了一个实例对象(只是保存的实例对象是不是当前的对象这一点区别而已),即: this 关键字也等同于一个指向对象的变量。于是按以上的变量查找链原理,this关键字同样会以函数作用域的嵌套层级关系进行逐层的向上寻找,默认的: 如果一个函数默认的未给定相应的调用方法,那么该函数则默认挂载在window全局对象上:

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

按推论,以上代码等同于如下代码:

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

即,如果函数未被指定为相关对象的方法的话,则默认被指定为全局对象window下的方法(也即通常所说的函数)。
经过以上分析,现在需要用几个示例来验证推论的结果是否正确。

第一个示例:

var obj = {
	field: "这个是一个属性",
	method: function(){
		console.log(this.field);
		console.log(this);
	}
}
obj.method();

该示例打印结果如下:
第一个示例的输出结果

结果分析: obj是一个对象,由于method是一个obj对象的方法,那么按之前的推导,this会找到当前的函数,但当前的函数已经是obj对象的method方法。此时通过对象调用该方法后this就指向了该对象,也即this就是obj对象。

第二个示例:

 var obj = {
	field: "这个是一个属性",
	method: function(){
		function fun(){
			console.log(this);
		}
		fun();
	}
}
obj.method();	// window

该示例打印结果如下:
第二个示例打印结果

结果分析: 由之前推导的原理可知,this函数是定义在fun函数当中,由于this首先寻找的是自己所在的函数是属于哪个对象上的。此时由于fun函数并没有声明是指向那个对象的,则默认指向为window全局对象下。所以打印结果即为window。

第三个示例:

function ObjectFun(){
	this.user = "这个是user";
	this.method = function(){
		console.log(this);
	}
	console.log(this);
}

var objectFun = new ObjectFun();	// 这里由于通过构造函数创建一个对象,所以会调用一次构造函数以初始化对象
objectFun.method();
ObjectFun();

该示例打印结果如下:
第三个示例输出结果

分析: 首先注意第一行输出结果,该输出结果为构造函数在创建对象时调用初始化输出的结果。第二个输出结果中可以看出当对象构造完毕,在调用时该函数已作为对象的方法来使用,所以打印的结果为该对象。第三个输出结果中得出的结论是: 由于该函数并不是作为对象的方法进行调用的,那么此时相当于被作为window全局对象的方法来调用,此时调用后this指向的则是window对象。

简单总结: this关键字会通过调用方进行判断,进而得出指向的属于谁。

最后,给出两个测试示例,如果明白了this关键字的原理,那么对于以下示例代码应该能很容易得出this指向的是哪个对象了。
测试用例1:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>this关键字解析</title>
	</head>
	<body>
		<input type="button" value="猜猜this指向的是不是window" id="btn" onclick="fun()" />
		<script>
			function fun(){
				console.log(this);		// 输出的是什么? window还是input表单?
			}
		</script>
	</body>
</html>

测试用例2:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>this关键字解析</title>
	</head>
	<body>
		<input type="button" value="猜猜this指向的是不是window" id="btn"/>
		<script>
			document.getElementById("btn").onclick =function(){
				console.log(this);		// 这个时候this指向的是window还是input表单?
			}
		</script>
	</body>
</html>

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: "this"关键字JavaScript中表示当前上下文中的对象。在函数中,"this"指向调用该函数的对象,而在全局作用域中,"this"指向全局对象(通常是window对象)。使用"this"关键字可以访问对象的属性和方法。 ### 回答2: JavaScript中的`this`关键字是一个非常重要的概念,它代表着当前函数的执行上下文(execution context)。它表示了当前代码正在执行的情境,在不同的情境下,`this`所代表的对象是不同的。 在全局作用域下,`this`指向的是全局对象,在浏览器中为`window`对象,在Node.js中为`global`对象。如下所示: ```javascript console.log(this === window); // true,在浏览器中输出 true ``` 当在一个函数中使用`this`关键字时,`this`所代表的对象会根据函数的调用方式而变化。常见的函数调用方式有四种,分别是函数调用、方法调用、构造函数调用和apply/call/bind方法调用。 1. 函数调用时,`this`指向全局对象或undefined(严格模式下)。 ```javascript function test() { console.log(this); } test(); // 全局作用域下 this 指向 window,输出 window ``` 2. 方法调用时,`this`指向调用该方法的对象。 ```javascript var person = { name: 'Tom', sayHello: function() { console.log('Hello, ' + this.name); } } person.sayHello(); // 方法调用,此时的 this 指向 person 对象,输出 Hello, Tom ``` 3. 构造函数调用时,`this`指向新创建的对象。 ```javascript function Person(name) { this.name = name; } var tom = new Person('Tom'); // 构造函数调用,此时的 this 指向新创建的对象 tom console.log(tom.name); // 输出 Tom ``` 4. apply/call/bind方法调用时,`this`指向指定的对象。 ```javascript var person1 = { name: 'Tom' }; var person2 = { name: 'Jerry' }; function sayName() { console.log('My name is ' + this.name); } sayName(); // 输出 My name is undefined sayName.apply(person1); // apply方法调用,此时的 this 指向 person1 对象,输出 My name is Tom var sayName1 = sayName.bind(person2); sayName1(); // bind方法调用,此时的 this 指向 person2 对象,输出 My name is Jerry ``` 总之,`this`关键字的作用非常重要,它可以让我们更加灵活地编写代码,但同时也需要注意使用它的场景和调用方式。 ### 回答3: JavaScript中的this关键字是一个非常重要的概念,它用于访问当前对象的上下文。它代表执行当前方法的对象。当我们在JavaScript中编写代码时,this关键字的上下文可以是全局对象,当前对象、任意对象或函数的作用域。 当我们在全局范围内使用this时,它将指向浏览器窗口或全局对象。而在对象里,this关键字则代表该对象。例如,如果我们在一个名为person的对象中使用this,它将返回person对象: ``` const person = { name: 'Tom', age: 30, greet() { console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`); } }; person.greet(); // 输出'Hello, my name is Tom and I am 30 years old.' ``` 当我们在函数内部使用this时,它可能会与预期的结果不同。在函数内部,this关键字通常为undefined。这是因为在JavaScript中,函数是一等对象,可以作为参数传递,并且可以按照不同的方式调用。因此,this关键字的上下文取决于如何调用该函数。 一种解决这个问题的方法是使用箭头函数。箭头函数的this关键字始终指向定义该函数的作用域: ``` const person = { name: 'Tom', age: 30, greet() { const sayHello = () => { console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`); } sayHello(); } }; person.greet(); // 输出'Hello, my name is Tom and I am 30 years old.' ``` 在这个例子中,箭头函数中的this关键字始终指向person对象。通过使用箭头函数,我们可以避免错误的this关键字上下文,并确保我们能够正确地访问对象的属性和方法。 总之,JavaScript中的this关键字非常重要,可以帮助我们访问当前对象的上下文。在函数内部使用时需要谨慎,可以考虑使用箭头函数来避免错误的上下文。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值