0

I find myself writing the following JavaScript more and more and I would like to know if this is a common pattern and if so, what is it called?

Part of the code and pattern:

var fruits = ["pear", "apple", "banana"];

var getNextFruit = function() {
    var _index = 0,
        _numberOfFruits = fruits.length;

    getNextFruit = function() {
        render(fruits[_index]);
        _index = (_index + 1) % _numberOfFruits;
    }
    getNextFruit();
};

I have a function which takes no parameters, inside the function I redefine the function and immediately call it. In a functional language this might be a function being returned, JavaScript just makes it easier because you can reuse the name of the function. Thus you are able to extend the functionality without having to change your implementation.

I can also imagine this pattern to be very useful for memoization where your "cache" is the state we wrap around.

I even sometimes implement this with a get or a set method on the function where I can get the state if it's meaningful. The added fiddle shows an example of this.

Because this is a primarily JavaScript oriented question: The obligatory fiddle

Mr. Baudin
  • 2,104
  • 2
  • 16
  • 24
  • Not sure what `render` does, but "producing" the elements of a collection one-by-one without caring about the underlying data type is called the [iterator](https://en.wikipedia.org/wiki/Iterator_pattern) pattern. – Balázs Édes Jun 12 '16 at 18:45
  • 1
    The pattern is called a "self-defining function", the name has been introduced in Stoyanov's book "Javascript Patterns" – Wiktor Zychla Jun 12 '16 at 18:46
  • Why wouldn't you define the `fruits` variable and array inside the function too? – nnnnnn Jun 12 '16 at 20:59
  • This is just a silly example, but imagine `fruits` coming from somewhere else, a service or a call to the server. Now I don't want to put all of *that* logic in there. Wrapping the reference to `fruits` in a self executing function is also something which would have made the code better... – Mr. Baudin Jun 13 '16 at 05:14

2 Answers2

2

I have a function which takes no parameters, inside the function I redefine the function and immediately call it. Is this is a valid pattern and what is it called?

A function redefining itself is usually an antipattern, as it complicates stuff a lot. Yes, it sometimes can be more efficient to swap out the whole function than to put an if (alreadyInitialised) condition inside the function, but it's very rarely worth it. When you need to optimise performance, you can try and benchmark both approaches, but otherwise the advice is to keep it as simple as you can.

The pattern "initialises itself on the first call" is known as laziness for pure computations (in functional programming) and as a singleton for objects (in OOP).

However, most of the time there's no reason to defer the initialisation of the object/function/module whatever until it is used for the first time. The ressources taken for it (both time and memory) are insignificant, especially when you are sure that you will need it in your program at least once. For that, use an IIFE in JavaScript, which is also known as the module pattern when creating an object.

Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • I need some more time to really wrap my head around this concept of laziness and how it would apply to JavaScript. I do think you might be right that this is meant to be a lazy implementation. – Mr. Baudin Jun 14 '16 at 05:56
1

Creating a function via a closure is a pretty common pattern in JavaScript. I would personally do that differently:

var fruits = ["pear", "apple", "banana"];

var getNextFruit = function(fruits) {
    var index = 0,
        numberOfFruits = fruits.length;

    function getNextFruit() {
        render(fruits[_index]);
        index = (_index + 1) % numberOfFruits;
    }

    return getNextFruit;
}(fruits);

There's no good reason (in my opinion) to clutter up the variable names with leading underscores because they're private to the closure anyway. The above also does not couple the workings of the closure with the external variable name. My version can be made a reusable service:

function fruitGetter(fruits) {
   var index = 0, numberOfFruits = fruits.length;

    function getNextFruit() {
        render(fruits[_index]);
        index = (_index + 1) % numberOfFruits;
    }

    return getNextFruit;
}

// ...

var getNextFruit = fruitGetter(someFruits);

var otherFruits = fruitGetter(["kumquat", "lychee", "mango"]);
Pointy
  • 405,095
  • 59
  • 585
  • 614
  • You are absolutely right about the underscore, there is no good reason except for some weird "coding standard" I normally use. Makes it easier to refactor and not miss a variable. To come back to the question, is a closure a pattern? Or is a closure just a language feature? – Mr. Baudin Jun 12 '16 at 18:36
  • 1
    A "closure" is a language feature. It's the term for the "object" that's created and sustained to hold the local variables that are "captured" when a function-returning-a-function is called (as in your code). – Pointy Jun 12 '16 at 18:38
  • And if you want to use underscores, then please do so and feel good about it. They just annoy me :) – Pointy Jun 12 '16 at 18:39
  • Thank you, yes, I had a feeling I was actually doing some OO in a weird way, I just can't find the actual name of the pattern behind it. – Mr. Baudin Jun 13 '16 at 05:10
  • I would love an IDE where the closed over variables has a different color but I think that's some other guy's rant ;) – Mr. Baudin Jun 13 '16 at 05:12