JavaScript - run once without booleans

后端 未结 9 1173
一个人的身影
一个人的身影 2021-01-30 17:42

Is there a way to run a piece of JavaScript code only ONCE, without using boolean flag variables to remember whether it has already been ran or not?

Spe

相关标签:
9条回答
  • 2021-01-30 17:50

    If not bound to an event, code is usually ran once

    0 讨论(0)
  • 2021-01-30 17:51

    In addition, the nature of what happens in the "/* do stuff here */" may leave something around that, when present, must mean that the function has run e.g.

    var counter = null;
    
    function initCounter() {
      if (counter === null) {
        counter = 0;
      }
    }
    
    0 讨论(0)
  • 2021-01-30 17:54
    (function (){
    
      var run = (function (){
    
        var func, blank = function () {};
    
        func = function () {
          func = blank;
    
          // following code executes only once 
          console.log('run once !');
        };
    
        return function(){
          func.call();
        };
      })();
    
      run();
      run();
      run();
      run();
    
    })();
    
    0 讨论(0)
  • 2021-01-30 17:58

    What about an immediately invoked anonymous function?

    (function () {
    
        // code in here to run once
    
    })();
    

    the code will execute immediately and leave no trace in the global namespace.

    If this code is going to need to be called from elsewhere, then a closure can be used to ensure that the contents of a function are run only once. Personally, I prefer this to a function that rewrites itself as I feel doing so can cause confusion, but to each their own :) This particular implementation takes advantage of the fact that 0 is a falsy value.

    var once = (function() {
      var hasRun = 0;  
      return function () {
        if (!hasRun) {
          hasRun++;   
    
          // body to run only once
    
          // log to the console for a test       
          console.log("only ran once");
        }              
      }
    })();
    
    // test that the body of the function executes only once
    for (var i = 0; i < 5; i++) 
      once();
    
    0 讨论(0)
  • 2021-01-30 17:58

    Elegant solution from Douglas Crockford, spent some time to understand how it works and stumbled upon this thread.

    So the wrapper once return function which is just invokes parameter's function you passed. And taking advantage of closures this construction replaced passed function to empty function, or null in original source, after the first call, so all the next calls will be useless.

    This is something very close to all other answers, but it is kinda self containing code and you could use it independently, which is good. I am still trying to grasp all the entire mechanism of replacement, but practically it just works perfectly.

    function once (func) {
    
     return function () {
       var f = func;
       func = null;
       return f.apply(this, arguments);
     };
    
    }
    
    function hi(name) {
      console.log("Hi %s", name);
    }
    
    sayonce = once(hi);
    sayonce("Vasya");
    sayonce("Petya");
    

    for those who are curious here is jsbin transformations

    0 讨论(0)
  • 2021-01-30 18:06

    An alternative way that overwrites a function when executed so it will be executed only once.

    function useThisFunctionOnce(){
       // overwrite this function, so it will be executed only once
       useThisFunctionOnce = Function("");
       // real code below
       alert("Hi!");
    }
    
    // displays "Hi!"
    useThisFunctionOnce();
    // does nothing
    useThisFunctionOnce();
    

    'Useful' example:

    var preferences = {};
    function read_preferences(){
       // read preferences once
       read_preferences = Function("");
       // load preferences from storage and save it in 'preferences'
    }
    function readPreference(pref_name){
        read_prefences();
        return preferences.hasOwnProperty(pref_name) ? preferences[pref_name] : '';
    }
    if(readPreference('like_javascript') != 'yes'){
       alert("What's wrong wth you?!");
    }
    alert(readPreference('is_stupid') ? "Stupid!" : ":)");
    

    Edit: as CMS pointed out, just overwriting the old function with function(){} will create a closure in which old variables still exist. To work around that problem, function(){} is replaced by Function(""). This will create an empty function in the global scope, avoiding a closure.

    0 讨论(0)
提交回复
热议问题