Singleton中的公共函数调用自身

Public function in Singleton calling itself

本文关键字:函数调用 Singleton      更新时间:2023-10-06

我试图使用singleton模式,但在实现递归公共函数时遇到了问题。

var singleton = (function(){
    var self = this;
    function privateFunc(){
        console.log('I can only be accessed from within!');
    }
    return{
        publicFunc: function(){
            //More stuff here
            setTimeout(self.publicFunc, 1000);
        }
    }
})();

我用singleton.publicFunc 来称呼它

我得到这个错误Uncaught TypeError: Cannot call method 'publicFunc' of undefined

我的理解是,var self实际上是这个实例中的Window对象,所以我必须传递singleton.publicFunc作为回调,这样才能工作,但它看起来不是很"DRY"(不要重复)。有吗在使用singleton时,有更好的方法来实现这一点吗?

使用API调用

var wikiAPI = (function(){
    var self = this;
    return {
      getRandomArticle : function() {
        return $.getJSON("http://en.wikipedia.org/w/api.php?action=query&generator=random&grnnamespace=0&prop=extracts&exintro=&format=json&callback=?", function (data) {
        });
      },
      fireAPICalls : function() {
        self.getRandomArticle().done(function(data) {
          for(var id in data.query.pages) {
            this.data = data.query.pages[id];
          }
          console.log(this.data);
          setTimeout(self.fireAPICalls, 1000);
        });
      }
    }
  })();

您可以使用这样的命名函数表达式:

var singleton = (function(){
    var self = this;
    function privateFunc(){
        console.log('I can only be accessed from within!');
    }
    return{
        publicFunc: function nameVisibleOnlyInsideThisFunction(){
                           //^-------------------------------^
            //More stuff here
            setTimeout(nameVisibleOnlyInsideThisFunction, 1000);
        }
    }
})();

我刚刚看到你的编辑。有一个对您试图调用的函数的引用会有所帮助。这样的东西怎么样:

var wikiAPI = (function(){
    var self = this;
    var randomArticle = function() {
        return $.getJSON("http://en.wikipedia.org/w/api.php?action=query&generator=random&grnnamespace=0&prop=extracts&exintro=&format=json&callback=?", function (data) {
        });
      };
    var repeatFunc = function fireApi() {
        randomArticle().done(function(data) {
          for(var id in data.query.pages) {
            this.data = data.query.pages[id];
          }
          console.log(this.data);
          setTimeout(fireApi, 1000);
        });
      };
    return {
      getRandomArticle : randomArticle,
      fireAPICalls : repeatFunc
    }
  })();

setTimeout()中使用bind将函数绑定到正确的作用域:

publicFunc: function() {
    setTimeout(this.publicFunc.bind(this), 1000);
}

演示:http://jsfiddle.net/te3Ru/

不能在IIFE中使用this。如果你想正确使用this,你需要创建一个函数的对象/实例,比如:

var singleton = (function () {
    // allow to omit "new" when declaring an object
    if (!(this instanceof singleton)) return new singleton();
    var self = this,                      // self now points to "this"
        privateFunc = function () {
            console.log('I can only be accessed from within!');
        };
    this.publicFunc = function() {
        console.log(this);                // this now points to the correct object
        setTimeout(function () {
            self.publicFunc.call(self);   // call function in the "self" scope
        }, 1000);
    };
    return this;
});
singleton().publicFunc();

它现在不是一个单例,但您可以拥有javascript所拥有的最接近privatepublic的东西!