【问题标题】:How can I scope this "public" method correctly?如何正确确定此“公共”方法的范围?
【发布时间】:2011-12-13 12:08:48
【问题描述】:

我有这个代码(JSFiddle)

var OBJ = function(){
    var privateVar = 23;
    var self = this;

    return {
        thePrivateVar : function() {
          return privateVar;
        },  

        thePrivateVarTimeout : function() {
            setTimeout(function() { alert(self.thePrivateVar()); } , 10);
        }
    }

}();

alert(OBJ.thePrivateVar());

OBJ.thePrivateVarTimeout();

这是我遇到的一个实际问题的抽象。

所以 - 我希望对 OBJ.thePrivateVarTimeout() 的调用等待 10 然后 alert 等待 23(我希望它通过其他公开的方法访问)。

但是self 似乎设置不正确。当我设置self = this 时,this 似乎不是对函数的引用,而是对全局对象的引用。这是为什么呢?

如何让公共方法thePrivateVarTimeout调用另一个公共方法thePrivateVar

【问题讨论】:

  • 为什么会这样?因为你是在正常调用函数(func())。在这种情况下,this 始终引用全局对象。如果您希望它引用一个空对象,请使用new 调用它或指定一个:var self = {};
  • @FelixKling 感谢这使得self 设置正确。我仍然不能用它来调用thePrivateVar。我认为 Raynos 的回答是我应该这样做的方式。

标签: javascript scope public-members


【解决方案1】:
var OBJ = (function(){
    var privateVar = 23;
    var self = {
        thePrivateVar : function() {
          return privateVar;
        },  

        thePrivateVarTimeout : function() {
            setTimeout(function() { alert(self.thePrivateVar); } , 10);
        }
    };

    return self;

}());

this === global || undefined 在调用的函数中。在 ES5 中,无论全局环境是什么,在 ES5 strict 中它是未定义的。

更常见的模式包括使用 var that = this 作为函数中的本地值

var obj = (function() {
  var obj = {
    property: "foobar",
    timeout: function _timeout() {
      var that = this;
      setTimeout(alertData, 10);

      function alertData() {
        alert(that.property);
      }
    }
  }

  return obj;
}());

或使用.bindAll 方法

var obj = (function() {
  var obj = {
    alertData: function _alertData() {
      alert(this.property);
    }
    property: "foobar",
    timeout: function _timeout() {
      setTimeout(this.alertData, 10);
    }
  }

  bindAll(obj)

  return obj;
}());


/*
    bindAll binds all methods to have their context set to the object

    @param Object obj - the object to bind methods on
    @param Array methods - optional whitelist of methods to bind

    @return Object - the bound object
*/
function bindAll(obj, whitelist) {
    var keys = Object.keys(obj).filter(stripNonMethods);

    (whitelist || keys).forEach(bindMethod);

    function stripNonMethods(name) {
        return typeof obj[name] === "function";
    }

    function bindMethod(name) {
        obj[name] = obj[name].bind(obj);
    }

    return obj;
}

【讨论】:

  • 谢谢,我使用了第一个模式。我真的不需要self 作为对整体OBJ 的引用——我只需要能够相互调用的公共方法。不过,Felix 也解决了 self 问题。
  • @ElRonnoco 我个人更喜欢.bindAll 模式,因为that = this 让我的眼睛流血。
  • @Raynos 在pd.bindAll(obj) 行中pd 是什么或者pd 来自哪里?
  • @cfontes 我内联了 bindAll 方法。
猜你喜欢
  • 1970-01-01
  • 2018-02-10
  • 1970-01-01
  • 1970-01-01
  • 2015-12-17
  • 1970-01-01
  • 2019-06-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多