对于那些来自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关键字来调用方法?
因为您将参数"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在第一次调用函数时被设置.
当第一次调用时sayHi("John");,this将指向全局对象window。这意味着this.tt = name实际上创建了一个全局tt变量。
然后,当您调用 时new sayHi("wallace");,this正确地指向 的新实例sayHi,但您返回另一个对象,而不是让new自然返回该实例。
如果您仔细查看对象文字,您会定义sslike ss: tt,。由于您没有使用this.tt并且在构造函数的范围中没有tt找到符号,因此该值将被解析为全局变量(之前设置为John)。
| 归档时间: |
|
| 查看次数: |
252 次 |
| 最近记录: |