确保函数的方法仅在对象文字内部调用一次

时间:2015-05-02 23:05:52

标签: javascript

SO上有很多方法可以确保只调用一次函数,但我找不到任何可以解决以下上下文和目标的方法。 上下文是对象文字中的一个函数,目标是将此实用程序放到Function.prototype上,或者以某种方式使其更简洁。 目前我这样做:

var HugeLiteral={
  subComponent:{
    _name:'subComponent'
    ,_privateFnsEtc:function(){
    }
    ,_init:function(){
      // start of thing I would like to "Macro-ize"
      if (arguments.callee.initialized) {console.error('already initialized');return;}
      arguments.callee.initialized=true;
      // End
      //
      // I would like to say something like
      if (!arguments.callee._proceed()) {return;}// _proceed logs the error
      //
      // or alternatively
      globalRunOnceCheckFn();// uses stack to get this function and do a throw
      // or 
      maybeWrapCallingFunction(this);
      // 
      codeToExecuteOnceHere();
      //
      // or this method which would tend to lock me into a single return point
      this._init=this._init.guardFnOnFunctionPrototype;
    }
  }
  ,_init:function(){
    // Here I could walk HugeLiteral and do whatever, 
    // but I am not sure I like wrapping the _inits.
  }
};

我的主要要求是这样做的方法必须在函数内部运行,我知道我可以在外部包装函数以使其运行一次。

2 个答案:

答案 0 :(得分:2)

var obj = {
    foo: function() {
        this.foo = function(){};
        return 'once';
    }
};

console.log(obj.foo()); // 'once'
console.log(obj.foo()); // undefined

答案 1 :(得分:0)

您可以使用IIFE闭包来存储变量,以跟踪它是否已经运行:

var obj = {
    myFunc: (function() {
        var alreadyRun = false;
        return function(arg1, arg2) {
            if (!alreadyRun) {
                alreadyRun = true;
                // rest of your code here
            }
        };
    })();
};

或者,您可以创建一个辅助函数,使用法更清晰,并且可以更容易地在多个位置重用此概念:

// helper function that returns a function stub that can only be called once
function allowRunOnce(fn) {
    var alreadyRun = false;
    return function() {
        if (!alreadyRun) {
            alreadyRun = true;
            return fn.apply(this, arguments);
        }
    }
}

var obj = {
    myFunc: allowRunOnce(function(arg1, arg2) {
        // code here for a method that can only be called once
    });
};