3

考虑这段代码:

hello我使用的功能this.msg中。这工作正常。但是,如果我不使用this. 为什么 JavaScript 会让人感到困惑,而在许多其他 OO 语言this中,它只用于使代码对读者显式?

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

8 回答 8

3

“为什么 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为其他对象的函数,如上例所示。

于 2013-07-06T04:06:58.360 回答
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以获取与此相关的更多信息。

于 2013-07-06T02:49:43.033 回答
1

您创建的是一个对象(或至少就 JS 而言)。当您想访问对象自己的属性时,您将需要使用this关键字。

JS 中的对象只是变量和函数的集合。当您想在其中使用对象自己的变量时,您需要使用this. 您已通过在对象定义中使用{}或大括号创建此对象。

在对象范围之外,您将需要使用<objectName>.var_or_func.

于 2013-07-06T02:54:03.097 回答
1

你编码的不是一个类,而是一个对象。

javascript 中的 this 一词与范围有关,而不与此代码和平所在的对象有关。

你可以通过这样做得到你想要的东西:

var smallMap = (function(){
    var msg = "Hellow ";

    return {
        hello : function(name) {
            console.log(msg + name);
        }
    }   

})();

也就是说你也不能使用this.msg。试试看,你会看到的。

于 2013-07-06T02:55:10.300 回答
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。如果答案是后者,我们应该使用smallMap.msg而不是this.msg内部函数 hello。TMHO当然...

于 2013-07-06T03:24:54.590 回答
0

在 Javascript 中,不可能静态确定this具有哪些属性。msg可以删除属性,或者可以将方法hello附加到新对象或作为普通函数调用。因此,Javascript 必须假设一个非限定标识符是指一个变量而不是一个对象属性,即使该对象碰巧有一个具有正确名称的属性。可以通过语句强制 Javascript 查看对象属性with,但是因为您无法分辨属性是什么,所以这通常被认为是一个可怕的想法。

于 2013-07-06T02:51:59.723 回答
0

使用对象字面量 ( { ... }) 与定义类不同。“hello”函数的作用域与您在外部定义它时的作用域相同,例如smallMap.hello = function() { ... }.

于 2013-07-06T02:53:08.063 回答
0

的原因this是为了让您可以在 的定义中编写arg1.func(arg2, arg3)和引用arg1as ,而不是编写。与其他静态解析的变量不同,它是动态解析的(这就是为什么没有它就无法访问的原因)。它的存在是为了方便调用“方法”的点表示法,它是 Java 开发人员的舒适毯子。(尽管由于 JavaScript 没有函数重载,xf(y,z) 为您提供了有用的函数命名空间。)thisfuncfunc(arg1, arg2, arg3)thismsgf

于 2013-07-06T04:00:50.530 回答