Implementing a 'once' function in JavaScri

2019-02-19 08:29发布

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.

3条回答
劳资没心,怎么记你
2楼-- · 2019-02-19 08:39

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.

查看更多
孤傲高冷的网名
3楼-- · 2019-02-19 08:45

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

查看更多
smile是对你的礼貌
4楼-- · 2019-02-19 08:52

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;
  }
}
查看更多
登录 后发表回答