解密JavaScript中的this关键字(介绍篇)

160 阅读4分钟

大家都知道,JavaScript中有一个关键字叫做this,但它与其他关键字如functionvarforif等不同,它的使用方式相对特殊,不那么容易理解。

this关键字会根据不同的执行上下文绑定到不同的对象,这正是它的神秘之处。

现在,让我们彻底搞清楚this关键字的绑定规则吧!

为什么使用this

在常见的编程语言中,几乎都有this这个关键字(Objective-C中使用的是self),但是JavaScript中的this和常见的面向对象语言中的this不太一样:

在大多数面向对象的编程语言中(如Java、C++、Swift、Dart等),this通常只出现在类的方法中,表示当前调用对象。 但是JavaScript中的this更加灵活,无论出现的位置或代表的含义都不尽相同。

那么,为什么要使用this关键字呢?让我们看下面的代码示例:

javascriptCopy code
var obj = {
  name: "why",
  running: function() {
    console.log(this.name + " is running");
  },
  eating: function() {
    console.log(this.name + " is eating");
  },
  studying: function() {
    console.log(this.name + " is studying");
  }
}

如果没有使用this,我们需要通过obj对象的引用来获取name属性,代码会是这样:

javascriptCopy code
var obj = {
  name: "why",
  running: function() {
    console.log(obj.name + " is running");
  },
  eating: function() {
    console.log(obj.name + " is eating");
  },
  studying: function() {
    console.log(obj.name + " is studying");
  }
}

然而,这样做存在一个问题:如果我们将obj的名称改为info,那么所有方法中的obj都需要修改为info。显然,这不是一个优雅的解决方案。

实际上,在实际开发中,我们通常使用this来优化上述代码:

javascriptCopy code
var obj = {
  name: "why",
  running: function() {
    console.log(this.name + " is running");
  },
  eating: function() {
    console.log(this.name + " is eating");
  },
  studying: function() {
    console.log(this.name + " is studying");
  }
}

通过使用this,我们可以轻松引用对象的属性。在API设计和一些函数或方法的编写中,使用this可以使代码更简洁、易于复用。

这只是使用this的一个示例,实际开发中我们会经常遇到各种使用场景,这也是this关键字难以理解的原因之一。

this指向何处

让我们先从最简单的情况开始,全局作用域下的this指向什么呢?

在浏览器中,this指向window对象。因此,在全局作用域下,可以认为this指向window

javascriptCopy code
console.log(this); // window

var name = "why";
console.log(this.name); // why
console.log(window.name); // why

然而,在实际开发中,很少直接在全局作用域下使用this,通常在函数中使用。

每当函数被调用时,JavaScript会创建一个执行上下文:

该上下文记录函数的调用栈、调用方式、传入的参数等信息,其中也包括this作为其中的一个属性。

现在,让我们看一个令人困惑的问题:

定义一个函数,并以三种不同方式调用它,结果会产生三种不同的输出。

javascriptCopy code
function foo() {
  console.log(this);
}

// 调用方式一:直接调用
foo(); // window

// 调用方式二:将`foo`放到一个对象中再调用
var obj = {
  name: "why",
  foo: foo
}
obj.foo(); // obj对象

// 调用方式三:使用`call`/`apply`调用
foo.call("abc"); // String {"abc"}对象

上述示例给我们带来了什么启示呢?

  1. 在函数调用时,JavaScript会默认为this绑定一个值;
  2. this的绑定与其定义位置无关;
  3. this的绑定与调用方式和位置有关;
  4. this是在运行时绑定的。

总结

本文对JavaScript中的关键字this进行了详细解析,让我们更好地理解了它的使用方式和绑定规则。

通过本文的学习,我们了解到为什么要使用this关键字,它能使代码更加优雅和易于维护。相比于直接引用对象的引用,使用this可以直接访问对象的属性,提高代码的可读性。

我们还学习到了this指向的对象。在全局作用域下,this指向window对象,但在实际开发中很少直接在全局作用域下使用this。每当函数被调用时,JavaScript会创建一个执行上下文,并将this作为其中的一个属性。通过示例,我们发现this的绑定与调用方式和位置有关,而不受其定义位置的影响。

最后,我们总结了this关键字的绑定规则:this是在运行时绑定的,具体的绑定规则取决于函数的调用方式和位置。

希望本文能够带给读者们关于this关键字的更深入理解,并且增加他们对JavaScript的兴趣和乐趣!

如果你觉得本文对你有帮助,别忘了点赞和收藏!这只是this指向的第一个模块,之后还会有更多文章来介绍this的其他方面。敬请期待!