关于Javascript中'this'关键字的混淆

sta*_*low 7 javascript this

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

我已经在互联网和StackOverflow上阅读了很多相关内容.喜欢这里这里.

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

我知道这一切,但是混乱还没有完全清除; 所以最好的理解方法是测试代码.


所以我决定编写一些小代码,我对这个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);
Run Code Online (Sandbox Code Playgroud)

正如预期的那样,警报窗口将显示(Hiiiiii May)然后(华莱士).现在请注意,该行sayHi("John");根本没有效果.

现在,当我改变一件事时,混乱将开始(改变var tt => this.tt):

 function sayHi(name){
   //this is the ONLY change I did.
   this.tt = name;
   return {
     ss: tt,
     work: function(anotherName){

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

// Now this line invocation will be problematic 
sayHi("John");


var hi2 = new sayHi("wallace");

hi2.work("May");
alert(hi2.ss);
Run Code Online (Sandbox Code Playgroud)

当警报方法(Hiiiiiii May)和(John)没有(华莱士)时,结果让我感到惊讶;

所以我有想法评论该行,sayHi("John");但这导致整个代码无法正常运行.

演示是在这里

我知道这可能是一个新问题.但这里真的很混乱,我确实尝试阅读很多文章和SO问题,但我忽略了这一点.

为什么这条线sayHi("John");将hi2.ss设置为John?为什么在删除代码时会破坏代码; 虽然我们之后sayHi使用new关键字来调用方法?

Poi*_*nty 6

因为您将参数"name"分配给引用的对象的属性this(在本例中将是window),所以对该文本对象的后续"tt"引用将是全局对象的"tt"属性,因为这是下一个封闭的范围.

您对"sayHi"的第一次调用是在没有new运算符的情况下进行的,因此该调用this将引用全局对象(window).第二个版本的第一行

this.tt = name;
Run Code Online (Sandbox Code Playgroud)

因此将设置window.tt为"约翰".

下一次调用是由new操作员完成的.因此,this在函数中引用了新实例化的对象.这条线

this.tt = name;
Run Code Online (Sandbox Code Playgroud)

因此,对任何事物都没有净影响,因为该函数在所有情况下都会返回不同的对象.测试的最后一行:

alert(hi2.ss);
Run Code Online (Sandbox Code Playgroud)

说"约翰",因为那是什么window.tt.为什么这么重要?因为"sayHi"返回一个具有从符号"tt"的值设置的属性("ss")的对象.范围内唯一的"tt"将window.tt在第一次调用函数时被设置.


pla*_*alx 3

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

然后,当您调用 时new sayHi("wallace");this正确地指向 的新实例sayHi,但您返回另一个对象,而不是让new自然返回该实例。

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