我正在阅读你不知道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();
如果您查看
bar
中的第一行,它将为foo
创建一个a
属性并为其分配值 42。如果我注释掉这一行,那么运行console.log(foo.hasOwnProperty('a'));
会给我错误。如果我让它运行,那么它返回 true。但如果是这样的话,那么调用bar
确实是在为 foo 创造一个a
属性,对吧?这就引出了问题3。我知道在这一点上
window.a
不存在。为什么这会返回
undefined
?this
应该下决心foo.a
,对吧?因为this
的上下文会在bar
,对吗?Bar
是呼叫站点。但是,无论是否注释掉foo.a = 42
,这仍然是undefined
。为什么在运行
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
为"通过"obj
,this
将指向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.a
和window.a
指的是同一件事。
因为这个上下文会在酒吧里,对吗?
不對。要使 bar 在 foo 中成为"this",您需要apply
或call
或bind
foo 传递您想要的"this"作为上下文。即
foo.call({});
or
foo.bind({});
将在foo
内制作"这个"和空对象。
为什么在运行 this.a++ 之后现在返回 true?如何以及为什么 正在创建全局变量?
出于同样的原因 - 当你这样做.a++时,你正在创建一个全局变量并递增一个a
1。