考虑这段代码:
在hello
我使用的功能this.msg
中。这工作正常。但是,如果我不使用this
. 为什么 JavaScript 会让人感到困惑,而在许多其他 OO 语言this
中,它只用于使代码对读者显式?
var smallMap = {
msg: "Hellow ",
hello: function(name) {
console.log(this.msg + name);
}
};
考虑这段代码:
在hello
我使用的功能this.msg
中。这工作正常。但是,如果我不使用this
. 为什么 JavaScript 会让人感到困惑,而在许多其他 OO 语言this
中,它只用于使代码对读者显式?
var smallMap = {
msg: "Hellow ",
hello: function(name) {
console.log(this.msg + name);
}
};
“为什么 JavaScript 会被混淆,”
它不是。它有一组特定的规则来管理对对象属性的访问如何工作。只是这些规则与所有其他 OO 语言都不相同。
“在许多其他 OO 语言
this
中,仅用于使代码对读者明确”
在某些OO 语言中,例如 Java,this
有时仅用于使代码对读者明确,但实际上它并不是完全可选的 - 它需要区分实例变量(成员)和其他同名变量(例如,方法中的局部变量)。
JavaScript 是面向对象的,但它没有类,也没有像 Java 等其他 OO 语言那样的成员方法。在 JavaScript 中,函数是一种对象,一般而言,任何变量或对象属性都可以设置为引用任何函数 - 因此,即使您在对象字面量中定义函数,例如函数不属于问题。一个例子:
function test1() {
alert('test1');
}
var obj1 = {
prop1 : 'obj1',
method1 : test1,
method2 : function() {
alert(this.prop1);
}
}
var test2 = obj1.method2;
obj1.method1(); // alerts 'test1'
test1(); // alerts 'test1'
obj1.method2(); // alerts 'obj1'
test2(); // alerts undefined (probably; see note below)
test2.call({prop1 : 'test2'}); // alerts 'test2'
delete obj1.method2; // remove the property
alert(obj1.method2); // alerts undefined - property no longer exists
test2.call({prop1 : 'test2'}); // alerts 'test2' - the function still exists
请注意,它obj1.method1
引用了在字面量之外定义的函数,该函数可以直接用 . 调用test1()
。同样,test2
已设置为引用已在文字中定义但可以直接调用的函数 - 即使您实际上删除了method2
您仍然可以test2()
直接调用的属性。
我定义了method2
/test2
以便它使用this.prop1
. 的值this
取决于函数的调用方式。如果你用“点”表示法调用它,obj1.method2()
那么函数内this
将是点之前的对象。如果您直接调用该函数,test2()
那么在非严格模式下this
将是window
,但在严格模式下可能是未定义的或其他一些值 - 有关更多详细信息,请参阅MDN。或者,您可以调用带有.call()
or.apply()
并显式设置this
为其他对象的函数,如上例所示。
因为this
在 Javascript 中是特殊的,并不总是适用于同一个对象。例如我可以这样做:
var smallMap = {
msg: "Hellow ",
hello: function(name) {
console.log(this.msg + name);
}
};
var smallMap2 = {
msg: "Hellow2 ",
hello: function(name) {
console.log(this.msg + name);
}
};
//here i set `this` to refer to `smallMap2` within smallMap
smallMap.hello.call( smallMap2, "the name" );
//will print "Hellow2 the name" instead of "Hellow the name"
this
指的是调用函数的对象,而不一定是函数所属的对象。有关更多详细信息,请参见:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this
您创建的是一个对象(或至少就 JS 而言)。当您想访问对象自己的属性时,您将需要使用this
关键字。
JS 中的对象只是变量和函数的集合。当您想在其中使用对象自己的变量时,您需要使用this
. 您已通过在对象定义中使用{}
或大括号创建此对象。
在对象范围之外,您将需要使用<objectName>.var_or_func
.
你编码的不是一个类,而是一个对象。
javascript 中的 this 一词与范围有关,而不与此代码和平所在的对象有关。
你可以通过这样做得到你想要的东西:
var smallMap = (function(){
var msg = "Hellow ";
return {
hello : function(name) {
console.log(msg + name);
}
}
})();
也就是说你也不能使用this.msg。试试看,你会看到的。
由于 Javascript 并不是真正面向对象的(它是原型的,意思是对象可以直接从其他对象继承),所以从作用域的角度来看,事情与 OO 的工作方式不同:
让我们以您的示例为例,并使用它来继承另一个对象的“hello”函数:
var new_obj;
new_obj.hello = smallMap.hello;
在那里,现在另一个对象具有相同的功能。唉,当这个函数将被调用时new_obj
,例如:
new_obj.hello("test");
除非我们定义new_obj.msg
,否则我们会得到undefinedtest
。
所以在这里我们应该小心:我们真正想要的是什么?使用new_obj.msg
或 始终使用smallMap.msg
。如果答案是后者,我们应该使用smallMap.msg
而不是this.msg
内部函数 hello。TMHO当然...
在 Javascript 中,不可能静态确定this
具有哪些属性。msg
可以删除属性,或者可以将方法hello
附加到新对象或作为普通函数调用。因此,Javascript 必须假设一个非限定标识符是指一个变量而不是一个对象属性,即使该对象碰巧有一个具有正确名称的属性。可以通过语句强制 Javascript 查看对象属性with
,但是因为您无法分辨属性是什么,所以这通常被认为是一个可怕的想法。
使用对象字面量 ( { ... }
) 与定义类不同。“hello”函数的作用域与您在外部定义它时的作用域相同,例如smallMap.hello = function() { ... }
.
的原因this
是为了让您可以在 的定义中编写arg1.func(arg2, arg3)
和引用arg1
as ,而不是编写。与其他静态解析的变量不同,它是动态解析的(这就是为什么没有它就无法访问的原因)。它的存在是为了方便调用“方法”的点表示法,它是 Java 开发人员的舒适毯子。(尽管由于 JavaScript 没有函数重载,xf(y,z) 为您提供了有用的函数命名空间。)this
func
func(arg1, arg2, arg3)
this
msg
f