JavaScript执行上下文中的this怎么使用

其他教程   发布日期:2023年07月12日   浏览次数:415

这篇文章主要讲解了“JavaScript执行上下文中的this怎么使用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“JavaScript执行上下文中的this怎么使用”吧!

前言

在对象内部的方法中使用对象内部的属性是一个非常普遍的需求。但是 JavaScript 的作用域机制并不支持这一点,基于这个需求,JavaScript 有另外一套 this 机制。

this 是和执行上下文绑定的,也就是说每个执行上下文中都有一个 this。执行上下文主要分为三种——全局执行上下文、函数执行上下文和 eval 执行上下文,所以对应的 this 也只有这三种——全局执行上下文中的 this、函数中的 this 和 eval 中的 this。

全局执行上下文中的 this

全局执行上下文中的

  1. this
是指向
  1. window
对象的。这也是
  1. this
和作用域链的 唯一交点,作用域链的最底端包含了
  1. window
对象,全局执行上下文中的
  1. this
也是指向
  1. window
对象。

函数执行上下文中的 this

  1. function foo() {
  2. console.log(this);
  3. }
  4. foo();

执行这段代码,打印出来的也是

  1. window
对象,这说明在默认情况下调用一个函数,其执行上下文中的
  1. this
也是指向
  1. window
对象的。

通常情况下,有下面三种方式来设置函数执行上下文中的

  1. this
值:

1. 通过函数的 call 方法设置

  1. let bar = {
  2. myName: "极客邦",
  3. test1: 1,
  4. };
  5. function foo() {
  6. this.myName = "极客时间";
  7. }
  8. foo.call(bar);
  9. console.log(bar);
  10. console.log(myName);

执行这段代码,你就能发现

  1. foo
函数内部的
  1. this
已经指向了
  1. bar
对象,因为通过打印
  1. bar
对象,可以看出
  1. bar
  1. myName
属性已经由“极客邦”变为“极客时间”了,同时在全局执行上下文中打印
  1. myName
,JavaScript 引擎提示该变量未定义。其实除了
  1. call
方法,你还可以使用
  1. bind
  1. apply
方法来设置函数执行上下文中的
  1. this

2. 通过对象调用方法设置

  1. var myObj = {
  2. name: "极客时间",
  3. showThis: function () {
  4. console.log(this);
  5. },
  6. };
  7. myObj.showThis();

执行这段代码,你可以看到,最终输出的

  1. this
值是指向
  1. myObj
的。所以,你可以得出这样的结论:使用对象来调用其内部的一个方法,该方法的
  1. this
是指向对象本身的。

接下来我们稍微改变下调用方式,把

  1. showThis
赋给一个全局对象,然后再调用该对象,代码如下所示:
  1. var myObj = {
  2. name: "极客时间",
  3. showThis: function () {
  4. this.name = "极客邦";
  5. console.log(this);
  6. },
  7. };
  8. var foo = myObj.showThis;
  9. foo();

执行这段代码,你会发现

  1. this
又指向了全局
  1. window
对象。

结论:

在全局环境中调用一个函数,函数内部的

  1. this
指向的是全局变量
  1. window

通过一个对象来调用其内部的一个方法,该方法的执行上下文中的

  1. this
指向对象本身。

3. 通过构造函数中设置

  1. function CreateObj() {
  2. this.name = "极客时间";
  3. }
  4. var myObj = new CreateObj();

当执行

  1. new CreateObj()
的时候,JavaScript 引擎做了如下四件事:

首先创建了一个空对象

  1. tempObj

接着调用

  1. CreateObj.call
方法,并将
  1. tempObj
作为
  1. call
方法的参数,这样当
  1. CreateObj
的执行上下文创建时,它的
  1. this
就指向了
  1. tempObj
对象

然后执行

  1. CreateObj
函数,此时的
  1. CreateObj
函数执行上下文中的
  1. this
指向了
  1. tempObj
对象

最后返回

  1. tempObj
对象
  1. var tempObj = {};
  2. CreateObj.call(tempObj);
  3. return tempObj;

这样,就通过

  1. new
关键字构建好了一个新对象,并且构造函数中的
  1. this
其实就是新对象本身。

this 的设计缺陷以及应对方案

1. 嵌套函数中的 this 不会从外层函数中继承

  1. var myObj = {
  2. name: "极客时间",
  3. showThis: function () {
  4. console.log(this);
  5. function bar() {
  6. console.log(this);
  7. }
  8. bar();
  9. },
  10. };
  11. myObj.showThis();

执行这段代码后,会发现函数

  1. bar
中的
  1. this
指向的是全局
  1. window
对象,而函数
  1. showThis
中的
  1. this
指向的是
  1. myObj
对象。

可以通过一个小技巧来解决这个问题,比如在

  1. showThis
函数中声明一个变量
  1. that
用来保存
  1. this
,然后在
  1. bar
函数中使用
  1. that
。其实,这个方法的的本质是把
  1. this
体系转换为了作用域的体系。

其实,你也可以使用 ES6 中的箭头函数来解决这个问题:

  1. var myObj = {
  2. name: "极客时间",
  3. showThis: function () {
  4. console.log(this);
  5. var bar = () => {
  6. console.log(this);
  7. };
  8. bar();
  9. },
  10. };
  11. myObj.showThis();

这是因为 ES6 中的箭头函数并不会创建其自身的执行上下文,所以箭头函数中的

  1. this
取决于它的外部函数。

2. 普通函数中的 this 默认指向全局对象 window

在实际工作中,我们并不希望函数执行上下文中的

  1. this
默认指向全局对象,因为这样会打破数据的边界,造成一些误操作。如果要让函数执行上下文中的
  1. this
指向某个对象,最好的方式是通过
  1. call
方法来显示调用。

可以通过设置 JavaScript 的 严格模式 来解决(在第一行加上

  1. "use strict";
)。在严格模式下,默认执行一个函数,其函数的执行上下文中的
  1. this
值是
  1. undefined

以上就是JavaScript执行上下文中的this怎么使用的详细内容,更多关于JavaScript执行上下文中的this怎么使用的资料请关注九品源码其它相关文章!