JavaScript 执行上下文的视角详解this使用

 更新时间:2023年02月27日 09:10:16   作者:codinglin  
这篇文章主要为以JavaScript 执行上下文的视角为大家讲清楚 this使用示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

前言

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

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

全局执行上下文中的 this

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

函数执行上下文中的 this

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

执行这段代码,打印出来的也是 window 对象,这说明在默认情况下调用一个函数,其执行上下文中的 this 也是指向 window 对象的。

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

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

let bar = {
  myName: "极客邦",
  test1: 1,
};
function foo() {
  this.myName = "极客时间";
}
foo.call(bar);
console.log(bar);
console.log(myName);

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

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

var myObj = {
  name: "极客时间",
  showThis: function () {
    console.log(this);
  },
};
myObj.showThis();

执行这段代码,你可以看到,最终输出的 this 值是指向 myObj 的。所以,你可以得出这样的结论:使用对象来调用其内部的一个方法,该方法的 this 是指向对象本身的。

接下来我们稍微改变下调用方式,把 showThis 赋给一个全局对象,然后再调用该对象,代码如下所示:

var myObj = {
  name: "极客时间",
  showThis: function () {
    this.name = "极客邦";
    console.log(this);
  },
};
var foo = myObj.showThis;
foo();

执行这段代码,你会发现 this 又指向了全局 window 对象。

结论:

在全局环境中调用一个函数,函数内部的 this 指向的是全局变量 window

通过一个对象来调用其内部的一个方法,该方法的执行上下文中的 this 指向对象本身。

3. 通过构造函数中设置

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

当执行 new CreateObj() 的时候,JavaScript 引擎做了如下四件事:

首先创建了一个空对象 tempObj

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

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

最后返回 tempObj 对象

var tempObj = {};
CreateObj.call(tempObj);
return tempObj;

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

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

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

var myObj = {
  name: "极客时间",
  showThis: function () {
    console.log(this);
    function bar() {
      console.log(this);
    }
    bar();
  },
};
myObj.showThis();

执行这段代码后,会发现函数 bar 中的 this 指向的是全局 window 对象,而函数 showThis 中的 this 指向的是 myObj 对象。

可以通过一个小技巧来解决这个问题,比如在 showThis 函数中声明一个变量 that 用来保存 this,然后在 bar 函数中使用 that。其实,这个方法的的本质是把 this 体系转换为了作用域的体系。

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

var myObj = {
  name: "极客时间",
  showThis: function () {
    console.log(this);
    var bar = () => {
      console.log(this);
    };
    bar();
  },
};
myObj.showThis();

这是因为 ES6 中的箭头函数并不会创建其自身的执行上下文,所以箭头函数中的 this 取决于它的外部函数。

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

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

可以通过设置 JavaScript 的 严格模式 来解决(在第一行加上 "use strict";)。在严格模式下,默认执行一个函数,其函数的执行上下文中的 this 值是 undefined

以上就是JavaScript 执行上下文的视角详解this使用的详细内容,更多关于JavaScript 执行上下文 this的资料请关注脚本之家其它相关文章!

相关文章

  • JavaScript 对象创建的3种方法

    JavaScript 对象创建的3种方法

    这篇文章主要给大家分享的时JavaScript 对象创建的3种方法,在 JavaScript中,对象是一组有属性名和属性值组成的无序集合,对象的创建可以通过对象字面量、new 关键字 和Object.create()函数来创建。
    2021-11-11
  • 微信小程序左滑删除效果的实现代码

    微信小程序左滑删除效果的实现代码

    这篇文章主要介绍了微信小程序左滑删除效果的实现代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-02-02
  • 微信小程序 MD5加密登录密码详解及实例代码

    微信小程序 MD5加密登录密码详解及实例代码

    这篇文章主要介绍了微信小程序 MD5加密登录密码详解及实例代码的相关资料,这里附有实例代码,需要的朋友可以参考下
    2017-01-01
  • JavaScript组合继承详解

    JavaScript组合继承详解

    这篇文章主要介绍了JavaScript组合继承,下面文章将围绕了JavaScript组合继承的相关资料展开详细内容,需要的小伙伴可以参考一下,希望对你有所帮助
    2021-11-11
  • Tree Shaking实现方法指南

    Tree Shaking实现方法指南

    这篇文章主要为大家介绍了Tree Shaking实现方法指南,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-03-03
  • 解析Javascript设计模式Revealing Module 揭示模式单例模式

    解析Javascript设计模式Revealing Module 揭示模式单例模式

    这篇文章主要为大家解析了Javascript设计模式Revealing Module 揭示模式及Singleton单例模式示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-08-08
  • 带你彻底理解JavaScript中的原型对象

    带你彻底理解JavaScript中的原型对象

    这篇文章主要介绍了带你彻底理解JavaScript中的原型对象,文中有详细的代码介绍,对正在学习js的小伙伴们有一定的帮助,需要的朋友可以参考下
    2021-04-04
  • TypeScript枚举类型

    TypeScript枚举类型

    这篇文章主要介绍了TypeScript枚举类型,所谓的枚举类型就是为一组数值赋予名字,下面我们来看看文章是怎么介绍的吧,需要的小伙伴也可以参考一下,希望对你有所帮助
    2021-12-12
  • 微信小程序中的swiper组件详解

    微信小程序中的swiper组件详解

    这篇文章主要介绍了微信小程序中的swiper组件详解的相关资料,需要的朋友可以参考下
    2017-04-04
  • 5种 JavaScript 方式实现数组扁平化

    5种 JavaScript 方式实现数组扁平化

    这篇文章主要介绍5种 JavaScript 方式实现数组扁平化,虽说只有5种方法,但是核心只有一个就是遍历数组arr,若arr[i]为数组则递归遍历,直至arr[i]不为数组然后与之前的结果concat。 想具体了解的小伙伴那请看下面文章内容吧
    2021-09-09

最新评论