将此对象存储在自定义私有变量中

Storing this object in custom private variable

我有这个 js 对象

var toggleItem = {

  attrData : '',
  toggleNew : '',
  toggleOld : '',
  //var self : this,

  init : function(){

    self = this;
    self.listener();
  },

  listener : function(){

    jQuery('.btn-save').click(function(){
      var current = this.id.split('_').pop();
      self.toggleNew = jQuery('.toggle-data-new_'+current).val();
      self.toggleOld = jQuery('.toggle-data-old_'+current).val();
      self.updateForm();
    });
   },

  updateForm : function(){

    jQuery('#toggle-product-form #new').val(self.toggleNew);
    jQuery('#toggle-product-form #old').val(self.toggleOld);
    jQuery('#toggle-product-form').submit();
  },

 }

过去我经常遇到 this 值被更改为我用 jQuery 引用的任何元素的问题。在这种情况下,我想将 this 存储在一个名为 self 的新变量中。但重要的是 self 不会在全球范围内可用。

您会看到我在对象顶部写的 //var self : this, 现在被注释掉了。这是因为将 var 放在它前面会在控制台中呈现此错误 - Unexpected identifier。但是,如果我删除 var 部分,我将它放在 init 函数(它是全局的)中,就会遇到与现在相同的问题。

问题我希望它对对象内部的所有对象都可用,而对对象外部的任何对象都可用?

无论哪种解决方案有效,我还计划将其应用于顶部声明的其他三个变量。

NB 我知道我可以使用对象的名称而不是 self 并让这个全局变量与其他东西发生冲突的风险相对较小,但我确信有是一种重新分配 this 值的方法,同时保持它只能从 toggleItem 对象中访问(以其当前形式)。

您只需要 listener 函数中的自我引用。尝试这样做:

var toggleItem = {
  // all your other stuff...
  listener: function() {
    var self = this;
    jQuery('.btn-save').click(function(){
      var current = this.id.split('_').pop();
      self.toggleNew = jQuery('.toggle-data-new_'+current).val();
      self.toggleOld = jQuery('.toggle-data-old_'+current).val();
      self.updateForm();
    });
  }
};

编辑:或者,您可以将所有对 self 的引用更改为 toggleItem,因为这正是您要访问的内容。如果你想声明一次 self 而不将它放在全局范围内,那么你可以使用非常类似的模块模式。

var toggleItem = (function() {
  var self = {
    // other stuff...
    listener: function() {
      jQuery('.btn-save').click(function(){
        var current = this.id.split('_').pop();
        self.toggleNew = jQuery('.toggle-data-new_'+current).val();
        self.toggleOld = jQuery('.toggle-data-old_'+current).val();
        self.updateForm();
      });
    }
  };
  return self;
})();

这会创建一个封闭的范围,因此 self 不会泄漏,它会立即调用该函数,因此 toggleItem 被分配了函数的 return 值。

以后要将成员变量设为私有,可以使用closure。这将防止变量泄漏到全局范围内。

function toggleItem() {
  var self = this,
  attrData = '',
  toggleNew = '',
  toggleOld = '';

  function init(){
    self.listener();
  }

  function listener(){
    jQuery('.btn-save').click(function(){
      var current = this.id.split('_').pop();
      self.toggleNew = jQuery('.toggle-data-new_'+current).val();
      self.toggleOld = jQuery('.toggle-data-old_'+current).val();
      self.updateForm();
    });
   }

  function updateForm(){
    jQuery('#toggle-product-form #new').val(self.toggleNew);
    jQuery('#toggle-product-form #old').val(self.toggleOld);
    jQuery('#toggle-product-form').submit();
  }

  return init;
 }

var toggle = toggleItem();
toggle.init();

我会遵循 Mike 的建议,但会采用完整的模块模式路线。如果您想收集任何常用功能,这将允许您拥有 "private" 功能。

使用此解决方案,我认为不需要 self 变量,除非您有其他未共享的内容。此处提供的 encapsulation 将所有内容都收集在一个函数中,并且您不会在对象上看到所有其他函数(这是将所有内容都扔到全局中的一个步骤范围,但您可以更进一步)。

var toggleItem = (function () {
    var self = this,
        attrData,
        toggleNew,
        toggleOld,
        init,
        listener,
        updateForm;

    init = function () {
        // This will call the "listener" function without the need for
        // "self", however you can specify it if you want to.
        listener();
    };

    listener = function () {
        jQuery('.btn-save').click(function () {
            var current = this.id.split('_').pop();

            // Again, you shouldn't need "self", but add it 
            // if it will ease your mind.
            toggleNew = jQuery('.toggle-data-new_' + current).val();
            toggleOld = jQuery('.toggle-data-old_' + current).val();
            updateForm();
        });
    };

    updateForm = function () {
        jQuery('#toggle-product-form #new').val(self.toggleNew);
        jQuery('#toggle-product-form #old').val(self.toggleOld);
        jQuery('#toggle-product-form').submit();
    };

    return {
        init: init
        // Add the other functions if you need to access them from outside 
        // the script here, but from what you showed, you should be fine
    }
}());