为什么"this"创建一个全局变量而不是使用调用站点中的变量?



我正在阅读你不知道JS的书,并且正在研究这个和对象原型

我知道this指的是什么,我需要查看呼叫网站。呼叫站点是this所指的。我不明白的是为什么这段代码没有像我认为的那样工作(我写它只是为了理解this,而不是为了任何工作问题或任何东西)。

function foo() {
console.log(foo.hasOwnProperty('a')); // 1
console.log(window.hasOwnProperty('a')); // 2
console.log(this.a); // 3
this.a++;
console.log(window.hasOwnProperty('a')); // 4
}
function bar(){
foo.a = 42;
foo();
}
bar();
  1. 如果您查看bar中的第一行,它将为foo创建一个a属性并为其分配值 42。如果我注释掉这一行,那么运行console.log(foo.hasOwnProperty('a'));会给我错误。如果我让它运行,那么它返回 true。但如果是这样的话,那么调用bar确实是在为 foo 创造一个a属性,对吧?这就引出了问题3。

  2. 我知道在这一点上window.a不存在。

  3. 为什么这会返回undefinedthis应该下决心foo.a,对吧?因为this的上下文会在bar,对吗?Bar是呼叫站点。但是,无论是否注释掉foo.a = 42,这仍然是undefined

  4. 为什么在运行this.a++之后,现在true返回?如何以及为什么要创建全局变量?

注意:这只是一种思考this的简单方法。在复杂情况下(例如使用.bind()或 OOP 时),以下内容可能不准确。

this,默认情况下 sorta 是指包含被调用函数的对象。例如,如果我这样做

var obj = {
fxn: function() {
console.log(this.bar);
},
bar: 3
}
obj.fxn(); // (1)
var fxn = obj.fxn();
fxn(); // (2)

(1)将"3"打印到控制台;因为在某种程度上,您称fxn为"通过"objthis将指向obj。换句话说,因为您正在调用存储在obj中的fxn副本,this将指向obj

(2)将(假设bar尚未在其他地方定义)打印未定义。那是因为fxn没有被称为"通过"任何东西。结果,它假装fxn是通过window调用的。

虽然在你的例子中,foo是在bar调用的,bar没有调用foo存在的版本......好吧,存储在自身内部。bar不打电话给foo..."通过"foo.

诚然,这很令人困惑。也许这会消除一些困惑:如果您将bar更改为:

function bar(){
foo.a = 42;
foo.foo = foo;
foo.foo();
}

它将打印42而不是未定义。重要的部分是foo正在调用的对象将是this.例如

function bar(){
var baz = {};
baz.a = 42;
baz.foo = foo;
baz.foo();
}

还将打印 42。

在 foo 中,this指的是父对象 - 即窗口。

所以this.awindow.a指的是同一件事。

因为这个上下文会在酒吧里,对吗?

不對。要使 bar 在 foo 中成为"this",您需要applycallbindfoo 传递您想要的"this"作为上下文。即

foo.call({});
or 
foo.bind({});

将在foo内制作"这个"和空对象。

为什么在运行 this.a++ 之后现在返回 true?如何以及为什么 正在创建全局变量?

出于同样的原因 - 当你这样做.a++时,你正在创建一个全局变量并递增一个a1。

最新更新