0
点赞
收藏
分享

微信扫一扫

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

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。


举报

相关推荐

0 条评论