考虑以下代码:
在hello
函数中,我使用this.msg
。这很好用。但是,如果我不使用this
,它会给出一个msg unefined错误。为什么JavaScript会混淆,而在许多其他OO语言this
仅用于向读者显示代码?
var smallMap = {
msg: "Hellow ",
hello: function(name) {
console.log(this.msg + name);
}
};
答案 0 :(得分:3)
因为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
答案 1 :(得分:3)
“为什么JavaScript混淆了”,
不是。它有一组特定的规则来管理对象属性的访问方式。只是这些规则与其他所有OO语言都不一样。
许多其他OO语言中的“
this
仅用于向读者显示代码”
在一些OO语言中,例如Java,this
有时用于使代码对读者明确,但实际上它不是完全可选的 - 它是 required 区分实例变量(成员)和同名的其他变量(例如,方法中的局部变量)。
JavaScript是面向对象的,但它没有类,也没有像其他一些OO语言(如Java)那样的成员方法。在JavaScript中,函数是一种对象,一般来说,任何变量或对象属性都可以设置为引用任何函数 - 所以即使你在对象文字中定义一个函数,就像在函数不是拥有的问题中一样/ em>由有问题的对象。一个例子:
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()
或.apply()
调用函数,并将this
显式设置为其他对象,如上例所示。
答案 2 :(得分:1)
您创建的是一个对象(至少就JS而言)。如果要访问对象自己的属性,则需要使用this
关键字。
JS中的对象只是变量和函数的集合。如果要在其中使用对象自己的变量,则需要使用this
。您已在对象的定义中使用{}
或大括号创建此对象。
在对象的范围之外,您需要使用<objectName>.var_or_func
。
答案 3 :(得分:1)
你编码的不是一个类,而是一个对象。
javascript中的这个词与范围有关,而不是与代码的和平相关的对象。
通过这样做你可以得到你想要的东西:
var smallMap = (function(){
var msg = "Hellow ";
return {
hello : function(name) {
console.log(msg + name);
}
}
})();
那说你也不能使用this.msg。试试吧,你会看到。
答案 4 :(得分:1)
由于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
。如果答案是后者,我们应该在函数hello中使用smallMap.msg
而不是this.msg
。 TMHO当然......
答案 5 :(得分:0)
在Javascript中,无法静态确定this
具有哪些属性。可以删除msg
属性,或者可以将hello
方法附加到新对象或称为普通函数。因此,Javascript必须假定非限定标识符引用变量而不是对象属性,即使该对象恰好具有正确名称的属性。可以强制Javascript使用with
语句查看对象属性,但由于您无法分辨属性是什么,这通常被认为是一个可怕的想法。
答案 6 :(得分:0)
使用对象文字({ ... }
)与定义类不同。 “hello”函数的范围与在外部定义它的范围相同,例如smallMap.hello = function() { ... }
。
答案 7 :(得分:0)
this
的原因是您可以在arg1.func(arg2, arg3)
的定义中撰写arg1
并将this
称为func
,而不是写{ {1}}。动态解析func(arg1, arg2, arg3)
与其他静态解析的变量不同(这就是为什么没有它就无法访问this
)。它可以帮助点'符号来调用'方法',它可以作为Java开发人员的舒适毯。 (虽然由于JavaScript没有函数重载,x.f(y,z)为函数msg
提供了有用的命名空间。)