this in JavaScript in detail

English 简体中文 繁体中文 ภาษาไทย Tiếng Việt
Summary

The this keyword in JavaScript is dynamically bound, with its value determined by the function's execution context rather than its definition. In global scope or pure function calls, this typically refers to the global object, becoming undefined in strict mode, whereas a method call sets this to the invoking object. When used in a constructor, this points to the newly created instance, but within nested functions, it often defaults back to the global object, requiring workarounds. To explicitly control this in such scenarios, or within callbacks and event handlers, developers can leverage call(), apply(), or bind(). Ultimately, this consistently references the object responsible for calling the function.

在JavaScript中,this 总是让人困惑,它是JavaScript中最常见的陷阱之一。 this 在JavaScript中不是一个好的设计(你可以参考JavaScript的一些其他设计缺陷这里),由于它的惰性绑定特性,它可以是一个全局对象,当前对象,或者... 有些人甚至避免在JavaScript中使用 this

实际上,如果你掌握了 this 的工作原理,你就会知道如何避开这些陷阱。 让我们看看在以下情况下 this 指向什么。

1. 在全局作用域代码中

alert(this)//window

在全局作用域代码中,this 将指向全局对象(通常在Web浏览器中是 window)。

2. 在纯函数调用中

function fooCoder(x) {
	this.x = x;
}
fooCoder(2);
alert(x);// 全局变量 x 的值为 2

这里 this 也指向全局对象,因为在全局作用域中定义的函数实际上是全局对象的一个方法。 所以 this 将是全局对象。 在严格模式下,this 将是 undefined

3. 在对象的方法调用中

var name = "clever coder";
var person = {
	name : "foocoder",
	hello : function(sth){
		console.log(this.name + " says " + sth);
	}
}
person.hello("hello world");

输出将是 "foocoder says hello world"。 this 将指向 person 对象,即调用该方法的当前对象。

4. 在构造函数中

new FooCoder();

在构造函数中,this 将指向使用 new 关键字新创建的对象。

5. 在私有函数调用中

var name = "clever coder";
var person = {
	name : "foocoder",
	hello : function(sth){
		var sayhello = function(sth) {
			console.log(this.name + " says " + sth);
		};
		sayhello(sth);
	}
}
person.hello("hello world");//clever coder says hello world

在私有函数中,this 不会绑定到外部方法的对象,而是绑定到全局对象。 这被认为是JavaScript的设计缺陷,因为没有人希望私有函数中的 this 在这里指向全局对象。 一般的解决方案是将 this 赋值给另一个变量,并在私有函数中引用该变量。

var name = "clever coder";
var person = {
	name : "foocoder",
	hello : function(sth){
		var that = this;
		var sayhello = function(sth) {
			console.log(that.name + " says " + sth);
		};
		sayhello(sth);
	}
}
person.hello("hello world");//foocoder says hello world

6. 在 call() 或 apply() 中

person.hello.call(person, "world");

apply()call() 类似,唯一的区别是第一个参数之后传入的参数。 在 apply() 中,其他参数将通过一个数组传递,而在 call() 中,其他参数将分别传递。

call( thisArg [,arg1,arg2,… ] );  // 参数列表,arg1,arg2,...
apply(thisArg [,argArray] );     // 参数列表,argArray

传入的第一个参数是 this 将指向的对象。 我们可以指定任何对象让 this 指向它。

7. 其他

我们可能会经常看到以下代码:

$("#some-ele").click = obj.handler;

如果我们在 handler 中使用 thisthis 会绑定到 obj 吗? 显然不会,在赋值之后,该函数在回调函数中被调用,this 将绑定到 $("#some-div") 元素。 这是我们需要理解的——执行上下文。

那么我们如何在回调函数中指定 this 对象为我们想要的对象呢? 在ECMAScript 5中,有一个 bind() 方法:

fun.bind(thisArg[, arg1[, arg2[, ...]]])

thisArg 将是我们想要成为的 this 对象。

$("#some-ele").click(person.hello.bind(person));

现在 this 将是 person 对象

在Prototype.js中,我们可以找到 bind() 的实现:

Function.prototype.bind = function(){
  var fn = this, args = Array.prototype.slice.call(arguments), object = args.shift();
  return function(){
    return fn.apply(object,
      args.concat(Array.prototype.slice.call(arguments)));
  };
};

结论

1. 当函数作为对象的方法被调用时,this 将指向该对象

2. 当在纯函数调用中时,this 将是全局对象(在严格模式下,this 将是 undefined

3. 在构造函数中,this 将是新创建的对象

一句话概括,this 总是指向调用该函数的对象。

JAVASCRIPT THIS BIND GUIDE

  RELATED

  COMMENTS

0

No comment for this article.