在JavaScript中实现“一次”功能

时间:2014-05-23 18:35:10

标签: javascript closures

我有来自Jasmine.js的这个规范测试once函数。我不知道如何实现这样的功能。

/* 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);
  });
});

我不太明白我该怎么做。我知道我应该做一次函数(myFunction){}但除此之外,我被困住了。我发现这与封闭有关,仍然无法绕过它。

3 个答案:

答案 0 :(得分:5)

从UnderscoreJS来源复制:

  _.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

答案 1 :(得分:4)

如果您不想使用UnderscoreJS,您可以自己实现更简单的“一次”功能:

var once = function (func) {
  var result;

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

    return result;
  }
};

当您将函数作为参数传递给此once函数(作为参数'func')时,它将返回一个只能调用一次的函数。

简而言之,它通过创建结果变量并为该变量分配使用其提供的参数调用函数的结果来实现此功能 - 但仅在第一次运行时 。否则,当随后调用该函数时,它将永远不会输入您的if语句(因为func变量在第一次调用中设置为null)和结果变量引用的值(在第一次调用期间设置并通过闭包访问)将被退回。

答案 2 :(得分:0)

非常非常小

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

(旧学校版)

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