Skip to main content

Creates a function that is restricted to the invoking parameter function once. Repeat calls to the function return the value of the first invocation. The function is invoked with the this binding and arguments of the created function.

/**
 * Creates a function that invokes `func`, with the `this` binding and arguments
 * of the created function, while it's called less than `n` times. Subsequent
 * calls to the created function return the result of the last `func`
 * invocation.
 *
 * @static
 *
 * @param {number} n The number of calls at which `func` is no longer invoked.
 * @param {Function} func The function to restrict.
 * @returns {Function} Returns the new restricted function.
 *
 * @example
 *
 * jQuery(element).on('click', before(5, addContactToList));
 * // => Allows adding up to 4 contacts to the list.
 *
 * @link https://lodash.com/docs/#before
 */
function before(n, func) {
    let result;

    if (typeof func !== "function") {
        throw new TypeError(
            "The second parameter (func) in before() must be a function."
        );
    }

    return function() {
        if (--n > 0) {
            result = func.apply(this, arguments);
        }

        if (n <= 1) {
            func = undefined;
        }

        return result;
    };
}

/**
 * Creates a function that is restricted to invoking `func` once. Repeat calls
 * to the function return the value of the first invocation. The `func` is
 * invoked with the `this` binding and arguments of the created function.
 *
 * @static
 *
 * @param {Function} func The function to restrict.
 * @returns {Function} Returns the new restricted function.
 *
 * @example
 *  var initialize = once(createApplication);
 *  initialize();
 *  initialize();
 *  // => `createApplication` is invoked once
 *
 * @link https://lodash.com/docs/#once
 */
function once(func) {
    return before(2, func);
}