Implementing a 'once' function in JavaScript

I have this spec from Jasmine.js which tests a once function. I'm not sure how to implement such a function though.

/* Functions that decorate other functions.  These functions return a version of the function
   with some changed behavior. */

// Given a function, return a new function will only run once, no matter how many times it's called
describe("once", function() {
  it("should only increment num one time", function() {
    var num = 0;
    var increment = once(function() {
      num++;
    });
    increment();
    increment();

    expect(num).toEqual(1);
  });
});

I don't quite understand what should I do here. I know I should make a function once(myFunction) {} but other than that, I am stuck. I figure out this has something to do with closures, still can't my head around it.

Answers:

Answer

Copied from the UnderscoreJS source:

  _.once = function(func) {
    var ran = false, memo;
    return function() {
      if (ran) return memo;
      ran = true;
      memo = func.apply(this, arguments);
      func = null;
      return memo;
    };
  };

http://underscorejs.org/docs/underscore.html

Answer

If you prefer not to use UnderscoreJS, you can implement a simpler "once" function yourself like this:

var once = function (func) {
  var result;

  return function () {
    if (func) {
      result = func.apply(this, arguments);
      func = null;
    }

    return result;
  }
};

When you pass your function as the argument to this once function (as the parameter as 'func'), it returns a function that can only be called once.

It accomplishes this feat, in short, by creating a results variable and assigning that variable the results of calling your function with its supplied arguments--but only the first time it is run. Otherwise, when the function is invoked subsequent times, it will never enter your if statement (because the func variable was set to null in the first invocation) and the value referenced by the results variable (set during the first invocation and accessed via closure) will be returned.

Answer

Very, very minimal

const once = fn => () => {
  if (!fn) return;
  fn();
  fn = null;
};

(Old school version)

function once(fn) {
  return function() {
    if (!fn) return;
    fn();
    fn = null;
  }
}

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.