首页 > 其他分享 >This:从执行上下文的角度来理解这个

This:从执行上下文的角度来理解这个

时间:2022-10-22 13:31:28浏览次数:54  
标签:上下文 函数 指向 对象 调用 角度 理解 执行

This:从执行上下文的角度来理解这个。

这在全局执行上下文中

让我们首先看看这在全局执行上下文中是什么。

可以在控制台输入console.log(this)在全局执行上下文中打印出这个,最后输出的是window对象。所以你可以得出结论,这在全局执行上下文中指向窗口对象。这也是This和scope链的唯一交集。作用域链的底部包含窗口对象,在全局执行上下文中也指向窗口对象。

这是在函数执行的上下文中

既然您知道全局对象中的这个对象指向窗口对象,那么让我们在函数执行的上下文中关注这个对象。或者先看看下面的代码:

函数foo() {

console . log(this);

}

foo();

复制代码

我们在foo函数中打印出这个值,当我们执行这段代码时,我们也打印出窗口对象,这意味着当一个函数被默认调用时,它的执行上下文中也指向窗口对象。你可能很好奇,但是你能在执行上下文中设置它指向其他对象吗?答案是肯定的。通常,在函数执行的上下文中有三种方法来设置该值。

1.由函数的调用方法设置。

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

让bar = {

我的名字:“名字1”,

测试1: 1,

};

函数foo() {

this.myName = " name2

}

foo.call(酒吧);

console . log(bar);

console.log(我的名字);

复制代码

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

实际上,除了call方法之外,您还可以使用bind和apply方法在函数执行的上下文中设置它,但是语法略有不同。

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

要在函数的执行上下文中更改这一点,除了函数的调用方法之外,还可以由对象调用,如下面的代码:

var myObj = {

姓名:“姓名”,

showThis: function () {

console . log(this);

},

};

myobj . show this();

复制代码

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

所以,你可以得出结论,用一个对象调用它内部的一个方法,方法的this指向对象本身。

其实你也可以认为,当JavaScript引擎执行myObject.showThis()时,它被转化为:


myObj.showThis.call(myObj)


接下来,让我们稍微改变一下调用方法,将showThis赋给一个全局对象,然后调用该对象。代码如下:

var myObj = {

名称:“时间”,

showThis: function () {

this.name = " bang

console . log(this);

},

};

var foo = myObj.showThis

foo();

复制代码

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

所以通过比较以上两个例子,可以得出以下两个结论:


在全局环境中调用一个函数,这个函数内部指向全局变量窗口。

在对象内部调用一个方法,这个方法的执行上下文中的this指向对象本身。


3.通过在构造函数中设置

您可以像下面这样在构造函数中设置它,如下面的示例代码所示:

函数CreateObj() {

this.name = " time

}

var myObj = new create obj();

复制代码

在这段代码中,我们使用new来创建对象myObj。你知道构造函数CreateObj中的这个指向谁吗?

实际上,当执行new CreateObj()时,JavaScript引擎会做以下四件事:


首先,一个空对象tempObj已创建;

然后调用CreateObj.call方法,使用tempObj作为调用方法的参数,这样在创建CreateObj的执行上下文时,其this指向tempObj对象;

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

最后,返回tempObj对象。


这样,我们通过new关键字构建了一个新对象,而这个在构造函数中实际上就是新对象本身。

设计缺陷及其解决方案

个人认为这不是一个好的设计,因为它的很多使用方法冲击了人的直觉,在使用过程中也有很多漏洞。让我们来看看这些设计缺陷。

1.嵌套函数中的这一点不会从外部函数中继承。

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

至于怎么解决?你可以在函数中声明一个变量self来保存它。当然,你也可以使用ES6中的箭头功能来解决这个问题。

2.这在普通函数中默认指向全局对象窗口。

如上所述,默认情况下调用一个函数,默认情况下,这个函数在其执行上下文中指向全局对象窗口。

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

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

摘要

审查以下内容:

首先,在使用这个的时候,为了避免坑,你要记住以下三点:


当一个函数作为一个对象的方法被调用时,函数中的这个就是对象;

正常调用函数时,在严格模式下,this的值是未定义的,在非严格模式下,this指向全局对象窗口;;

嵌套函数中的This不继承外部函数的这个值。


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


标签:上下文,函数,指向,对象,调用,角度,理解,执行
From: https://blog.51cto.com/u_15840034/5785808

相关文章

  • 深度学习模型训练的过程理解(训练集、验证集、测试集、batch、iteration、epoch、单步
    呜呜呜呜,感谢大佬学弟给我讲干货.本来是讨论项目的,后面就跑偏讲论文模型了. 解答了我一直以来的疑问:数据放模型里训练的过程. 假设我们有一个数据集26304条数据,假设设置模......
  • 一张图来帮你理解 SOA
    SOA曾经一度是技术领域中最难以理解的一个概念。SOA似乎让很多人感到困惑-一般来讲这是由于人们认为它拥有几乎神奇的力量。事实上SOA只是一个很......
  • 关于web应用上下文Context
      关于web应用上下文Context  很多朋友都对Context不太了解,他们说"项目中没看到这个对象啊""但是老是听人提起Context","经常看到ServletContext,PageContext.EJBConte......
  • 嵌入式-C语言基础:理解形参和实参的区别
    #include<stdio.h>//实参:函数原型中声明函数后面带的参数inttest(intx)//函数原型{//函数体printf("test里面的x地址=%p",&x);returnx;}//变量......
  • 用99乘法表帮助理解for循环
    目录用99乘法表帮助理解for循环一、99乘法表的shell脚本二、拆分脚本各行三、延展的另一写法用99乘法表帮助理解for循环一、99乘法表的shell脚本[rocky8.6]vim99.sh......
  • 深入理解蓝牙mesh的行为
    目的此文档的目的在于引导读者思考蓝牙mesh行为,并非一篇完善的mesh行为描述文档。什么是蓝牙mesh的行为蓝牙mesh的行为就是指,一个设备在处于某些特定的角色,并开启特......
  • TS语法中interface和class的理解
    在TS中interface和后端语言如c#中的概念是不一样的,在TS中interface相当于定义了一种类型,是设置自定义类型的方式,区分与基础类型(number、string等),当定义变量时,就可以设置该......
  • 理解卷积
    卷积的公式为 公式中包含1个f函数,1个g函数,f函数乘g函数再积分,便是卷积操作。我们可以把f函数当做“生产力”,g函数当做“留存率”。随着时间t的变化,生产的东西越来越多,......
  • python当中自定义上下文管理器
    在python当中,我们知道with的用法,是一种上下文管理机制。比如withopen(file,'w')asf: 这种方法下,就集成了open和close.我们也可以自定义一个上下文管理器。方法一:c......
  • 关于报出这样的错误:org.apache.catalina.core.StandardWrapperValve.invoke 在路径为/
    从23:30开始报错检查,现在才弄好,发出来分享一下错误界面:首先,我们需要检查一下我们利用DBUtil.java文件中引用的db文件名称是否正确,(我就是因为没有注意到文件名称是否正确......