Optimizing your JavaScript with Functional Programming

DZone 's Guide to

Optimizing your JavaScript with Functional Programming

· Performance Zone ·
Free Resource


Generally speaking, there are many ways to optimize your code. For instance, you could re-evaluate your core algorithms and perhaps try to speed up the execution of some loops. Also, you can adopt some best practices like avoiding large string concatenation or excessive use of closures. But, instead of reducing the execution time of your functions, what if you could avoid calling unnecessary functions? Being that JavaScript is a functional programming language, there are a couple of techniques we can use to reduce the execution time of your programs:

  1. Lazy Evaluation
  2. Memoization

Before we get started, here are some concepts you will need to understand in order make sense of the rest: 

Pure functions: A function is pure when it has no side effects, i.e does not read/modify any external data.

Referential transparency (RT): Piggy-backing on pure functions, RT functions are ones which compute their return values based solely on the input provided. It's the closest thing to a mathematical function. Because its result is consistent with respect to the input, RT functions are very easy to reason about and test. 

Now, Let's jump in: 

Lazy Evaluation

In JavaScript, function composition plays an important part in implementing lazy evaluation. Lazy evaluation is a “call by need” execution strategy whereby a function is invoked only when needed. Non-strict languages like Haskell have built-in lazy evaluation consistently in every call; however, JavaScript is a strict language, which means that all functions are evaluated eagerly. Consider the following example: Suppose we wanted to extract a finite subset of numbers from an infinite set. What? Bear with me. We can create a function called range(begin, end) which creates an array of whole numbers from a specified beginning to end:

var firstTenItems = range(1, Infinity).take(10);

firstTenItems();//-> 1, 2, 3, 4....10?

You might wondering: how can this function call ever terminate if we are generating an infinite list of numbers? In a non-strict language like Haskell, we could write an equivalent program that will actually terminate and take the first 10 items, efficiently. In JavaScript, this similar program will generate an infinite loop since it will try to eagerly evaluate the range function first. Because lazy evaluation is not built-in to JavaScript, the only alternative is to emulate it with an API, which is based on functional composition in order to circumvent JavaScript’s eager evaluation mechanism at its core by a functional library called Lazy.js. 

 var evenNumbers = Lazy.generate(function (x) {           
        return 2 * x;
    }); //-> 2, 4, 6, 8,...


The Lazy.generate function is essentially a stream data structure. A stream is an array-like data structure that behaves very closely to a linked list (in a language like Java). It can be used to generate an infinite amount of elements. While this sounds bizarre, behind the scenes it is the power of lazy evaluation via function composition that allows this to happen. The code previously shown is a classical problem of separating a function that can generate infinite number of possible values, and a selector that chooses the appropriate ones.

Using Lazy.js allows us to modularize this program effectively as the initialization of the number stream is deferred until the each function is called. Without it, you would be forced to write code like looks similar to: 

var threshold = 10;
for (var i = 0; i < Infinity; i+=2) {
  if (i >= threshold) {
  else {
    var item = items[i]; 

    // do work on item

This one-off code isn’t reusable at all, takes longer to write and it’s harder to maintain. Using Lazy.js we will avoid writing code like this in favor of a more declarative approach that takes advantage of lazy evaluation. Because it avoids unnecessary computations (or at the very least defer to only when needed), lazy evaluation has also shown to speed up the execution of JavaScript programs. 


Another form of laziness is by avoiding computing a function call altogether. In traditional object-oriented systems this is accomplished by placing a cache or proxy layer that is checked before a function is called. Upon return, the result of the function is given a key that references it uniquely and this key-value pair is persisted in the cache.

Functional languages implement a caching mechanism akin to the object-oriented model but built-in to the platform so a function’s result is stored and can be retrieved when calling it again with the same input. This technique is called Memoization and it relies on the notion of referentially transparent functions. Recall that pure functions always return the same value on same inputs.
Through Memoization the set of input parameters are encoded as the key to a function’s result, internally cached, and looked up when the function is invoked again on the same input.

Consider a function that computes a secure hash based on a user’s unique username and password. Depending on the type of algorithm used, this function can be very expensive to call. Generally, with secure encryption the more intense the algorithm the stronger the hash will be. 

function generateSecureHash(username, password) {
 // run expensive algorithm

 return hash;
generateSecureHash('jim', 'Jim@Pwd!');

Based on the premise of pure functions, calling generateSecureHash again on this same input bypasses the computation and returns the memorized result. The effectiveness of Memoization is directly proportional to the level modularity in your code. As you decompose big tasks into a greater number of smaller, single-purpose functions, Memoization can be used to achieve a higher level of fine-grained caching.

Like lazy evaluation, Memoization is not a native JavaScript feature, but can be installed by augmenting JavaScript’s extensible Function object, and looks like this: 

var computeFactors = (function factors(num) {

// run algorithm

 return factors;

computeFactors(100); //-> [1,2,4,8,16,32,64]

Again, subsequent calls with 100 will be lazy and just return the memorized result. The beauty of this level of caching in functional languages and in JavaScript is can be implemented without adding any boilerplate code of placing cache checks/adds all over our functions. Here's a look at implementing memoization by extending the Function object: 

Function.prototype.memoized = function (key) {

        if (this.length === 0) {
            console.log("Cannot memoize function call with empty arguments");
        else {
            // Handle identifiable objects
            if (key.getId && (typeof key.getId === 'function')) {
                // Extract objs ID
                key = key.getId();
            else {
                // Last resort, handle objects by JSON-stringifying them
                if (!isNumeric(key) && !isString(key)) {
                    // stringify key
                    key = JSON.stringify(key);

        // Create a local cache
        this._cache = this._cache || {};
        var val = this._cache[key];

        if (val === undefined || val === null) {
            //alert("Cache miss, apply function");
            console.log("Cache miss");
            val = this.apply(this, arguments);
            this._cache[key] = val;
        else {
            console.log("Cache hit");
        return val;

    // Enhance Function prototypes

    // Provide ability for functions to memoize (or be proxied)
    Function.prototype.memoize = function () {

        var fn = this;

        if (fn.length === 0 || fn.length > 1)
            return fn;  // only handle functions with a single formal argument

        return function () {
            return fn.memoized.apply(fn, arguments);

Functional languages cede mechanisms for lazy evaluation to the language platform and free developers from having to worry about implementing and testing this. In JavaScript, we can do the same by letting with high-level constructs like compose and memoize handle any optimizations in our code. This is preferable because it means that we are free to test our functions independently of any optimization mechanism. Hopefully we've enjoyed this blog post and begin to embraces functional programming is your programming paradigm of choice! Stay tuned for more! 


  1. http://danieltao.com/lazy.js/
functional programming, java, java 8 functional programming, javascript, performance

Published at DZone with permission of Luis Atencio , DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}