关于';这';Javascript中的关键字

关于';这';Javascript中的关键字,javascript,this,Javascript,This,我可以说,对于那些来自C#等语言的人来说,“this”关键字是Javascript中最令人困惑的部分 我在网上和StackOverflow上读到了很多关于这方面的文章。喜欢和 我知道“this”关键字将绑定到上下文。在构造函数中,它将绑定到正在创建的对象,当没有即时上下文时,它将绑定到全局对象(即窗口) 我知道这一切,但困惑仍未完全消除;因此,最好的理解方法是测试代码 所以我决定写一些小代码,我对这个关键字的复杂程度感到惊讶 以下是我测试的代码: function sayHi(name){

我可以说,对于那些来自C#等语言的人来说,“this”关键字是Javascript中最令人困惑的部分

我在网上和StackOverflow上读到了很多关于这方面的文章。喜欢和

我知道“this”关键字将绑定到上下文。在构造函数中,它将绑定到正在创建的对象,当没有即时上下文时,它将绑定到全局对象(即窗口)

我知道这一切,但困惑仍未完全消除;因此,最好的理解方法是测试代码


所以我决定写一些小代码,我对
这个
关键字的复杂程度感到惊讶

以下是我测试的代码:

 function sayHi(name){
   var tt = name;
   return {
     ss: tt,
     work: function(anotherName){

     alert ("hiiiii    " + anotherName);
   }
 };
}

//this method invocation has no effect at all right now
sayHi("John");


var hi2 = new sayHi("wallace");

hi2.work("May");
alert(hi2.ss);
正如预期的那样,警报窗口将显示(Hiiiiii May),然后显示(wallace)。现在请注意,
sayHi(“John”)完全无效

现在,当我只更改一件事情时,就会出现混乱(change var tt=>this.tt):

结果让我惊讶,当警报方法发出(Hiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii

所以我有了一个想法,对这句话
sayHi(“John”)
但这导致整个代码无法正常工作

我知道这可能是个新手问题。但这里真的很混乱,我也试着读了很多文章和问题,但我忽略了这一点


为什么这句话
sayHi(“John”)将hi2.ss设置为John??为什么我们删除它时它会破坏代码;尽管我们在后面使用
new
关键字调用
sayHi
方法,因为您将参数“name”分配给
this
引用的对象的属性(在本例中为
window
),但在该对象文本中对“tt”的后续引用将是“tt”属性,因为这是下一个封闭范围

您第一次调用“sayHi”时没有使用
new
操作符,因此在该调用
中,此
将引用全局对象(
窗口
)。第二个版本中的第一行

this.tt = name;
因此将
window.tt
设置为“John”

下一个呼叫由
新的
操作员进行。因此,
函数中的此
引用新实例化的对象。线路

this.tt = name;
因此对任何事情都没有净影响,因为函数在所有情况下都返回不同的对象。测试的最后一行:

alert(hi2.ss);

说“John”是因为这是
window.tt
中的内容。这有什么关系?因为“sayHi”返回一个对象,其属性(“ss”)由符号“tt”的值设置。作用域中唯一的“tt”将是
window.tt
,它是在第一次调用函数时设置的。

调用构造函数时,如果函数中不存在return语句,则隐式返回
,否则返回值,并且只忽略


在第二个示例中,您将name参数保存为
this.tt
,但返回一个不同的对象。这就是事情不起作用的原因。基本上使用
这个
或返回一个自定义对象,但不要两者都做。

当您第一次调用
sayHi(“John”)
将指向全局对象
窗口
。这意味着
this.tt=name
实际上创建了一个全局
tt
变量

然后当你调用
newsayhi(“华莱士”)
正确地指向了
sayHi
的一个新实例,但您正在返回另一个对象,而不是让
new
自然返回该实例


如果仔细查看对象文字,您可以像
ss:tt,
那样定义
ss
。由于您没有使用
this.tt
,并且在构造函数的作用域中找不到
tt
符号,因此该值将被解析为全局变量(以前设置为
John
)。

在“严格”模式下,当在没有任何上下文的情况下调用函数时,
this
未定义的
ss:tt,
是基于本地变量而不是此变量的属性进行赋值的,因为该变量不存在,所以应该是未定义的。@scragar在向下阅读答案并理解所有答案之后。现在你的评论有意义了。谢谢你的回答。。但我还是很困惑。所以你说当我调用sayHi(“john”)时,“this”是(window),然后它是window.tt=john。。。但是为什么当我用新创建的对象(hi2)再次调用该方法时,hi2.tt仍然是john而不是wallace??我还是很困惑。。进一步感谢Instrumentonit的“John”,因为在第二次调用中,
这个
不是
窗口
——您用
新的
来调用它。非常清楚。感谢您的耐心,但现在我的问题如下:第一次致电sayHi(“john”)给了我一个变量(window.tt=“john”);但是第二个调用(hi2=newsayhi(“wallace”)应该给我另一个变量(hi2.tt=“wallace”)…你是说tt是不允许在本地使用的,因为它是全局设置的吗?不,它不是
hi2.tt
-它是由于你通过
new
调用函数而创建的全新对象。函数的第一行将成功地将该对象的“tt”属性设置为“wallace”,但随后你将“ss”设置为纯“tt”而不是“this.tt”.我爱你,伙计..虽然这里的所有答案都很有用;但是你提醒我我犯了一个对象文字错误。当我将
ss:tt
定义为
ss:this.tt
时,代码的行为与预期的一样…现在我明白了。我是否可以编辑你的答案,以便以正确的格式添加代码?@stackunderflow我是glad I可以提供帮助。附加到
this
的实例变量和用
var
声明的函数范围变量是两个非常不同的东西。Acc
alert(hi2.ss);