为什么我需要使用“this”来访问地图中的值?

时间:2013-07-06 02:45:27

标签: javascript oop

考虑以下代码:

hello函数中,我使用this.msg。这很好用。但是,如果我不使用this,它会给出一个msg unefined错误。为什么JavaScript会混淆,而在许多其他OO语言this仅用于向读者显示代码?

var smallMap = {
    msg: "Hellow ",
    hello: function(name) {
        console.log(this.msg + name);
    }
};

8 个答案:

答案 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

另请查看callapplybind,了解与此相关的更多信息。

答案 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.prop1this的值根据函数的调用方式设置。如果用“点”表示法调用它,如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提供了有用的命名空间。)