2014-11-03 61 views
3

这是一个关于性能和最佳实践的问题。Javascript static/singelton - this vs _this vs object name

假设我有一个js对象,它封装了大量的辅助方法。该对象被视为静态类,这意味着它永远不会实例化,它的所有方法基本上都是辅助方法。 当使用事件和jQuery时,对象的this作用域不断变化,并且由于它有相当多的方法,我在想什么是最佳做法 - 在每个方法的开始将this保存为_this,或者仅使用对象名称MyObject

多年来,我一直在做这两个,当谈到singelton /静态对象,但我认为必须有一个最佳实践,是时候采取最好的方法。

我目前的研究表明,来用_this而不是直接调用MyObject的好处主要有两个:

  • 如果对象的名称更改,_this永远是可行的
  • 可能更快(虽然没有看到性能测试结果),因为浏览器保持在相同的范围内,并且不需要每次都找出MyObject的范围。使用MyObject

优点:

  • 更少的代码编写。
  • 垃圾收集管理? (少变量分配)
  • 可能对一些开发商(其中多个this适用)更具可读性
  • 更容易重构代码,因为MyObject永远是可行的

我想知道是否有一种方法全局保存_this(只在对象的范围内),并避免在每个方法的开始处分配它。如果没有 - 是否还有其他我缺少的优点/缺点,或者直接调用对象名称被认为是不好的做法。

这是一个简化的参考对象(真实对象有更多的方法)。

var MyObject = { 
     init: function() { 

     this.registerEvents(); 
     //other stuff 

     }, 
     registerEvents: function() { 

     this.registerOnSomeEvent(); 
     //registering more events.. 
     //... 

     }, 

     registerOnSomeEvent: function() { 
      var _this = this; 
      jQuery('#someid').click(function() { 
      _this.doSomething();//option 1 
      MyObject.doSomething();//option 2 
      }); 
     }, 

     doSomething: function() { 
     //doing something... 
     } 
    } 

MyObject.init(); 

谢谢你的帮忙!

回答

5

可以封装整个对象在一个封闭来实现这一点没有对每个功能specifiying _this

window.MyObject = (function() { 
    var self = { 
     init: function() { 

      self.registerEvents(); 
      //other stuff 

     }, 
     registerEvents: function() { 

      self.registerOnSomeEvent(); 
      //registering more events.. 
      //... 

     }, 

     registerOnSomeEvent: function() { 
      jQuery('#someid').click(function() { 
       self.doSomething();//option 1 
       self.doSomething();//option 2 
      }); 
     }, 

     doSomething: function() { 
      //doing something... 
     } 
    }; 

    self.init(); 

    return self; 
})(); 
+0

我喜欢这个解决方案,但由于我们再次使用'self'作为对象名称,它真的和直接调用'MyObject'完全不同吗?性能明智我的意思 – Yani 2014-11-03 20:58:06

+1

@Yani老实说,除非你正在访问变量1000s甚至每秒甚至数百万次,这并不重要。您应该首先优化可读性和减少错误。 – 2014-11-03 21:05:43

+1

@Yani没有意义的性能差异。嵌入式引用全局变量的主要优点在于,通过这种方法,'self'不能改变 - 全局变量可能会发生变化。 – Pointy 2014-11-03 21:25:33

3

我觉得你的问题是,你去的刻意模仿的东西,你应该做的,而不是一个很长的路要走。

const mySingleton = (function() { 
    // Instance stores a reference to the Singleton 
    var instance; 
    function init() { 
     // Singleton 
     // Private methods and variables 
     var privateVariable = "Im also private"; 
     var privateRandomNumber = Math.random(); 

     return { 
      // Public methods and variables 
      publicMethod: function() { 
       console.log("The public can see me!"); 
      }, 
      publicProperty: "I am also public", 
      get randomNumber() { 
       return privateRandomNumber; 
      } 
     }; 
     function privateMethod(){ 
      console.log("I am private"); 
     } 

    }; 
    return { 
     // Get the Singleton instance if one exists 
     // or create one if it doesn't 
     get instance() { 
      if (!instance) instance = init(); 
      return instance; 
     } 
    }; 
})(); 

如果你不想用不完this背景下,从来没有使用继承和永远不会有一个以上的实例就是不写那些东西作为对象的方法,而是宣布,在私有方法一个singleton pattern(这是一个揭示模块模式,但只有一个实例)

因为它基本上就是这样做,但你揭示了一切,你几乎没有任何目的地发送this数百和数百次。 this不是经常设计的。不要这样使用它。

+0

你是对的,因为我来自服务器端语言,我试图模仿静态类行为。我不知道你可以做你描述的+1。但是,它没有回答如何处理范围更改的事件和jQuery? – Yani 2014-11-03 21:04:36

+0

*作用域*永远不会改变。使用这种模式,任何事情都会在100%的时间内引用相同的事物。上下文(* this *)发生了变化,但从不是范围。但你根本不用担心* this *,因为在这种模式下你根本不会使用它。 – Winchestro 2014-11-03 21:05:55

+1

如果您还没有,请查看http://www.addyosmani.com/resources/essentialjsdesignpatterns/book/。它是一本免费的在线书,详细介绍了(当然)javaScript设计模式,包括“揭示模块”模式。 – 2014-11-03 21:16:13

相关问题