Использование переменной как объекта и функции

Я пытаюсь высмеять функцию times из библиотеки JavaScript Underscore.js.

Эта функция принимает два синтаксиса:

_.times(3, function(n) {
    console.log("hello " + n);
});

и

_(3).times(function(n) {
    console.log("hello " + n);
});

До сих пор мне удалось издеваться над первым, создав объект _ следующим образом:

var _ = {
    times: function(reps, iteratee) {
        // a loop
    }
};

И второй синтаксис, создав функцию _, которая возвращает объект:

function _(n) {
    return {
        times: function(iteratee) {
            // a loop
        }
    };
}

Но я не могу использовать эти два метода вместе. Мне нужно найти способ, который позволит использовать оба синтаксиса. Вы знаете, как я мог использовать символ _ как объект, а также функцию?

Ответ 1

Функции - это объекты в Javascript, поэтому вы можете просто сделать что-то вроде этого:

var _ = function(a,b) { /* ... */ };
_.times = _;

Ответ 2

Вы можете объединить два синтаксиса следующим образом:

var _ = (function() {

    var times = function(n, iteratee) {
        // a loop
    };

    function _(n) {
        return {times: function(iteratee) {
            return times(n, iteratee);
        }}; // or shorter: {times: times.bind(null, n)}
    }

    _.times = times;

    return _;
})();

Здесь вы получаете выгоду от того, что функции также являются объектами и, следовательно, могут иметь свойства.

Ответ 3

Вы можете расширить функцию после ее определения. Попробуйте следующее:

function _(n) {
  return {
    times: function(iteratee) {
      while (n-- > 0)
        iteratee();
    }
  };
}

_.times = function(reps, iteratee) {
  while (reps-- > 0)
    iteratee();
};

function iter() {
  console.log('iter!');
}

_(3).times(iter);

console.log('----');

_.times(5, iter);