0

我有一个与 JavaScript 对象初始化符号有关的问题。我对上面的示例有效,因为它指的是定义中实例的名称,我感到有些惊讶。这两种方法是否相同?我通常使用第二种方法,但它们似乎达到了同样的效果。

var myObj = 
{
   Message:"Test",
   someMethod:function(){
      $.get("/someUrl",function(){
        myObj.Message = "Returned Value";
      })
   }
}

var myObj = 
{
   Message:"Test",
   someMethod:function(){
      var that = this; //have to capture this in order to use it in a different context.
      $.get("/someUrl",function(){
        that.Message = "Returned Value";
      })
   }
}

我想顶级方法有优势,因为您不必跟踪当前含义,this因为它可能会在不同的上下文中发生变化。还有其他区别吗?

编辑:了解顶级方法并不总是推荐的方法,但我想在某些情况下我仍然看到一些优势。一种这样的情况是 KnockoutJS,其中绑定解析将重新定义this视图模型上绑定点击处理程序的含义。更多信息:http: //www.appliness.com/10-things-to-know-about-knockout-js-on-day-one/

在这种情况下,我将不得不手动记录当前含义this

我通常使用第二种方法,但我只是想完全理解差异以及它为什么起作用:-)。绝对理解它只适用于单实例场景。

4

2 回答 2

1

JavaScript 的闭包语义在这里有点有趣。实际上,它们将捕获当前分配给的变量,尽管逻辑可能表明该变量尚不存在。

这实际上是 JavaScript变量提升的结果。在分配变量之前,必须先声明它。因此,即使在myObj不在全局范围内的情况下,它仍然会被函数捕获,因为实际上,您正在编写以下代码:

var o = (function () {
    var myObj; // hoisted declaration
    myObj = {
        message: "test",
        someMethod: function () { alert(myObj.message); },
    };
    return myObj;
})();
o.someMethod(); // alerts 'test'

但是,这并不总是有效。如果您可以强制分配给它的变量超出闭包的范围,则该变量确实是未定义的。

function createObj() {
    return {
        message: "test",
        someMethod: function () { alert(myObj.message); },
    };
}

var o = (function () {
    var myObj;
    myObj = createObj();
    return myObj;
})();
o.someMethod(); // error: myObj is not defined

因此,虽然有时使用该名称可能会奏效,但它是一种更加脆弱的方法。如果名称没有被捕获,或者变量的名称在内部被重用,它可能会完全中断。在重构时使用名称而不是使用this会导致代码中断,即使只是简单地移动代码也是如此,如果您没有意识到问题出在哪里,调试起来可能会很痛苦。

基本上,虽然第一种方法有时可能会起作用,但它不是一个通用的解决方案,并且与仅使用相比没有太大的优势this,因此最好使用它this

于 2013-10-16T05:54:51.130 回答
1

this由 JS 解释器根据调用方式设置。当您有一个类型的对象的多个实例时,它非常有用(并且基本上是必需的),因为this它是唯一知道要引用哪个对象的对象,因此建议您使用第二个代码示例。

任何对象方法调用obj.method()都将导致this自动设置为obj方法内部。

如果您有一个单例(只有一个对象的实例),那么您当然可以根据需要使用命名变量,但通常不需要使用名称,因为this如果您编写访问对象方法的代码就可以了适当地。

于 2013-10-16T05:50:25.813 回答