返回顶部
首页 > 资讯 > 前端开发 > JavaScript >深入理解函数执行上下文this
  • 675
分享到

深入理解函数执行上下文this

函数执行上下文this执行上下文this 2022-11-13 18:11:23 675人浏览 八月长安
摘要

目录javascript 中的 this 是什么全局执行上下文中的 this函数执行上下文中的 this1. 通过函数的 call 方法设置2. 通过对象调用方法设置3. 通过构造函

JavaScript 中的 this 是什么

关于 this,我们得先从执行上下文说起。我们知道:执行上下文中包含了变量环境、词法环境、外部环境,当然也包括 this,具体你可以参考下图:

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

不过由于 eval 我们使用的不多,所以本文我们对此就不做介绍了,如果你感兴趣的话,可以自行搜索和学习相关知识。

那么接下来我们就重点讲解下全局执行上下文中的 this和函数执行上下文中的 this。

全局执行上下文中的 this

首先我们来看看全局执行上下文中的 this 是什么。

你可以在控制台中输入console.log(this)来打印出来全局执行上下文中的 this,最终输出的是 window 对象。所以你可以得出这样一个结论:全局执行上下文中的 this 是指向 window 对象的。这也是 this 和作用域链的唯一交点,作用域链的最底端包含了 window 对象,全局执行上下文中的 this 也是指向 window 对象。

函数执行上下文中的 this

现在你已经知道全局对象中的 this 是指向 window 对象了,那么接下来,我们就来重点分析函数执行上下文中的 this。还是先看下面这段代码:

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

我们在 foo 函数内部打印出来 this 值,执行这段代码,打印出来的也是 window 对象,这说明在默认情况下调用一个函数,其执行上下文中的 this 也是指向 window 对象的。估计你会好奇,那能不能设置执行上下文中的 this 来指向其他对象呢?答案是肯定的。通常情况下,有下面三种方式来设置函数执行上下文中的 this 值。

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

你可以通过函数的call方法来设置函数执行上下文的 this 指向,比如下面这段代码,我们就并没有直接调用 foo 函数,而是调用了 foo 的 call 方法,并将 bar 对象作为 call 方法的参数。

let bar = {
  myName: " name1 ",
  test1: 1,
};
function foo() {
  this.myName = " name2 ";
}
foo.call(bar);
console.log(bar);
console.log(myName);

执行这段代码,然后观察输出结果,你就能发现 foo 函数内部的 this 已经指向了 bar 对象,因为通过打印 bar 对象,可以看出 bar 的 myName 属性已经由“name1”变为“name2”了,同时在全局执行上下文中打印 myName,JavaScript 引擎提示该变量未定义。

其实除了 call 方法,你还可以使用bind和apply方法来设置函数执行上下文中的 this,仅仅是语法稍有不同。

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

要改变函数执行上下文中的 this 指向,除了通过函数的 call 方法来实现外,还可以通过对象调用的方式,比如下面这段代码:

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

在这段代码中,我们定义了一个 myObj 对象,该对象是由一个 name 属性和一个 showThis 方法组成的,然后再通过 myObj 对象来调用 showThis 方法。执行这段代码,你可以看到,最终输出的 this 值是指向 myObj 的。

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

其实,你也可以认为 JavaScript 引擎在执行myObject.showThis()时,将其转化为了:

myObj.showThis.call(myObj)

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

var myObj = {
  name: " time ",
  showThis: function () {
    this.name = " bang ";
    console.log(this);
  },
};
var foo = myObj.showThis;
foo();

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

所以通过以上两个例子的对比,你可以得出下面这样两个结论:

  • 在全局环境中调用一个函数,函数内部的 this 指向的是全局变量 window。
  • 通过一个对象来调用其内部的一个方法,该方法的执行上下文中的 this 指向对象本身。

3. 通过构造函数中设置

你可以像这样设置构造函数中的 this,如下面的示例代码:

function CreateObj() {
  this.name = " time ";
}
var myObj = new CreateObj();

在这段代码中,我们使用 new 创建了对象 myObj,那你知道此时的构造函数 CreateObj 中的 this 到底指向了谁吗?

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

  • 首先创建了一个空对象 tempObj;
  • 接着调用 CreateObj.call 方法,并将 tempObj 作为 call 方法的参数,这样当 CreateObj 的执行上下文创建时,它的 this 就指向了 tempObj 对象;
  • 然后执行 CreateObj 函数,此时的 CreateObj 函数执行上下文中的 this 指向了 tempObj 对象;
  • 最后返回 tempObj 对象。

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

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

就我个人而言,this 并不是一个很好的设计,因为它的很多使用方法都冲击人的直觉,在使用过程中存在着非常多的坑。下面咱们就来一起看看那些 this 设计缺陷。

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

我认为这是一个严重的设计错误,并影响了很多开发者。

至于如何解决?你可以在函数中声明一个变量 self 用来保存 this。当然也可以使用 es6 中的箭头函数来解决这个问题。

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

上面我们已经介绍过了,在默认情况下调用一个函数,其执行上下文中的 this 是默认指向全局对象 window 的。

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

这个问题可以通过设置 JavaScript 的“严格模式”来解决。在严格模式下,默认执行一个函数,其函数的执行上下文中的 this 值是 undefined,这就解决上面的问题了。

总结

回顾下内容:

首先,在使用 this 时,为了避坑,你要谨记以下三点:

  • 当函数作为对象的方法调用时,函数中的 this 就是该对象;
  • 当函数被正常调用时,在严格模式下,this 值是 undefined,非严格模式下 this 指向的是全局对象 window;
  • 嵌套函数中的 this 不会继承外层函数的 this 值。

最后,我们还提了一下箭头函数,因为箭头函数没有自己的执行上下文,所以箭头函数的 this 就是它外层函数的 this。

以上就是深入理解函数执行上下文 this的详细内容,更多关于函数执行上下文 this的资料请关注编程网其它相关文章!

--结束END--

本文标题: 深入理解函数执行上下文this

本文链接: https://lsjlt.com/news/170051.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 深入理解函数执行上下文this
    目录JavaScript 中的 this 是什么全局执行上下文中的 this函数执行上下文中的 this1. 通过函数的 call 方法设置2. 通过对象调用方法设置3. 通过构造函...
    99+
    2022-11-13
    函数执行上下文 this 执行上下文 this
  • JavaScript函数执行上下文的this怎么调用
    今天小编给大家分享一下JavaScript函数执行上下文的this怎么调用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。Ja...
    99+
    2023-07-04
  • 深入学习JavaScript执行上下文
    目录前言初始化全局对象(GO)执行上下文全局执行上下文Java Script遇到函数代码如何执行?环境变量和记录总结:前言 我们先不看这个标题,来看下面这段代码是怎么运行的: var...
    99+
    2022-11-13
    JavaScript执行上下文 JavaScript上下文
  • JavaScript 执行上下文的视角详解this使用
    目录前言全局执行上下文中的 this函数执行上下文中的 thisthis 的设计缺陷以及应对方案1. 嵌套函数中的 this 不会从外层函数中继承2. 普通函数中的 this 默认指...
    99+
    2023-02-27
    JavaScript 执行上下文 this JavaScript this
  • JavaScript执行上下文中的this怎么使用
    这篇文章主要讲解了“JavaScript执行上下文中的this怎么使用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“JavaScript执行上下文中的this怎么使用”吧!前言在对象内部的方...
    99+
    2023-07-05
  • Kotlin协程上下文与上下文元素深入理解
    目录一.EmptyCoroutineContext二.CombinedContext三.Key与Element四.CoroutineContext五.AbstractCoroutin...
    99+
    2022-11-13
    Kotlin 协程上下文 Kotlin 上下文
  • Python上下文管理器深入讲解
    目录引子概念上下文管理协议(Context Management Protocol)上下文管理器(Context Manager)引子 上下文管理器是一种简化代码的有力方式,其内部也...
    99+
    2022-12-21
    Python上下文管理器 Python上下文
  • javascript执行上下文详解
    目录简介javascript代码的执行过程编译阶段var变量提升与let和const作用域单个执行上下文中变量的查找规则调用栈作用域链词法作用域闭包闭包的回收从上下文角度讲this简...
    99+
    2023-05-18
    javascript执行上下
  • 怎么理解JS栈和执行上下文
    本篇内容主要讲解“怎么理解JS栈和执行上下文”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么理解JS栈和执行上下文”吧! 栈栈,存储货物或供旅客住宿...
    99+
    2024-04-02
  • Python深入02 上下文管理器
    上下文管理器(context manager)是Python2.5开始支持的一种语法,用于规定某个对象的使用范围。一旦进入或者离开该使用范围,会有特殊操作被调用 (比如为对象分配或者释放内存)。它的语法形式是with...as...关闭文件...
    99+
    2023-06-02
  • 深入解析Python中的上下文管理器
    1. 上下文管理器是什么? 举个例子,你在写Python代码的时候经常将一系列操作放在一个语句块中: (1)当某条件为真 执行这个语句块 (2)当某条件为真 循环执行这个语句块 有时候我们需要在当程序在...
    99+
    2022-06-04
    上下文 管理器 Python
  • C++ 函数调试详解:如何深入了解函数的执行过程?
    c++++ 函数调试的关键技能包括:1. 设置断点以暂停执行;2. 单步执行逐行查看代码;3. 检查变量监视值;4. 打印调试信息查看特定状态。通过实战案例,可以深入了解函数执行过程,快...
    99+
    2024-05-03
    c++ 函数调试
  • 深入理解Spring Aop的执行顺序
    首先回忆一下 AOP 的常用注解 @Before:前置通知:目标方法之前执行 @After:后置通知:目标方法之后执行 @AfterReturning:返回...
    99+
    2024-04-02
  • 深入理解JavaScript的事件执行机制
    目录前言 浏览器 JS 异步执行的原理 浏览器中的事件循环 执行栈与任务队列 宏任务和微任务 Async/await的运行顺序特点示例 个人分析前言 熟悉事件循环,了解浏览器运行机...
    99+
    2024-04-02
  • 深入理解:Mysql执行SQL语句过程
     开发人员基本都知道,我们的数据存在数据库中(目前最多的是mysql和oracle,由于作者更擅长mysql,所以这里默认数据库为mysql),服务器通过sql语句将查询数据的请求传入到mysql数据库。数据库拿到sql语句以后。...
    99+
    2023-06-02
  • 深入理解JVM字节码执行引擎
    我们都知道,在当前的Java中(1.0)之后,编译器讲源代码转成字节码,那么字节码如何被执行的呢?这就涉及到了JVM的字节码执行引擎,执行引擎负责具体的代码调用及执行过程。就目前而言,所有的执行引擎的基本一致:输入:字节码文件处理:字节码解...
    99+
    2023-06-02
  • 输入npm run xxx后执行原理深入解析
    目录前言package.json文件总结前言 当我们输入npm run XXX会首先去package.json文件里找scripts 里找对应的xxx,然后执行 xxx的命令,例如我...
    99+
    2024-04-02
  • 深入了解 PHP 函数文档
    php 函数文档是开发人员了解函数用法的宝贵资源,步骤包括:访问函数文档(php 手册或 help 函数);理解函数语法(函数名、参数、返回值、异常);了解函数参数(类型、描述、默认值)...
    99+
    2024-04-13
    函数 php
  • 深入理解Go语言文档中的flag.StringVar函数解析命令行参数
    在Go语言中,我们有时需要通过命令行传递参数给程序。为了方便用户设置参数,Go语言提供了flag包来解析命令行参数。其中flag.StringVar函数是flag包中最常用的函数之一,它可以帮助开发者快速的定义并解析命令行参数。本文将深入分...
    99+
    2023-11-03
    Go语言 命令行参数 flagStringVar
  • 深入理解C++函数栈帧
    目录一、什么是函数栈帧二、具体原理2.1 main函数的调用2.2 sum函数的调用参考:一、什么是函数栈帧 每一次函数调用都是一个过程,为函数开辟栈空间,用于本次函数调用中临时变量...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作