A few days ago, a colleague of mine asked me out of the blue whether or not the following is a good JavaScript question to ask a “senior front-end engineer” interviewee.

Implement the “add” function which works as follows:
add(1, 2); // 3
add(1)(2); // 3
add(1, 2, 3); // 6
add(1)(2)(3); // 6

At first glance, I thought to myself: “Pfft, this is easy. Adding numbers?”. Upon further inspection I realized the trick to this question is in the number of ways this function can be called. The function needs to somehow know whether to return a value (the sum) or return itself so it can sum the next number. The remaining part of this post was the thought process I had while attempting to solve this seemingly easy interview question.


So we need to to somehow determine whether to return a value or a function, but first let’s tackle the first part of the question by coming up with a way to sum numbers n number of arguments. In JavaScript, functions have access to an arguments variable that is a array-ish object. We can use this variable to access the numbers passes in by the function callee.

var add = function() {
    var nums = Array.prototype.slice.call(arguments);
    return nums.reduce(function(prev, curr) {
        return prev+curr;
    });
};

Cool, this works for the first way of using the function, but how would we implement add to support the second way? Add is returning a function that then proceeds to be called with the subsequent number as the argument. So what we need is a function scope to capture the sum and an inner function (that gets returned) that acts as the accumulator.

var add = function(i) {
    var sum = i;
    var adder = function(num) {
        if (num) {
            sum += num;
        }
        return adder;
    };
    return adder;
};

The implementation above calculates the sum but never gives us a way to get it. Luckily there are a couple methods on Object that we can define get our value. toString and toValue are methods that returns a primitive (string or value) presentation of the object. We define the valueOf and the toString method on the adder function so we can use it to access our sum.

var add = function(i) {
    var sum = 0;
    var adder = function adder(num) {
        if (num) {
            sum += num;
        }
        return adder;
    };
    adder.valueOf = function() {
        return sum;
    };
    adder.toString = function() {
        return sum;
    };
    adder(i);
    return adder;
};

We combine our two implementations (for the two forms) to get our final implementation.

var add = function(i) {
    var sum = 0;
    var adder = function adder(num) {
        if (arguments.length > 1) {
            var nums = Array.prototype.slice.call(arguments);
            sum += nums.reduce(function(prev, curr) {
                return prev+curr;
            });
        } else {
            sum += num;
        }
        return adder;
    };
    adder.valueOf = function() {
        return sum;
    };
    adder.toString = function() {
        return sum;
    };
    adder.apply(adder, arguments);
    return adder;
};