JavaScript Functions that Return Functions

By  on  

A few weeks back, I tweeted that I loved functions that returned functions. I got quite a few replies to the tune of....WTF?!  It's important that people understand the value of functions that return functions;  using this technique can save you code, JavaScript efficiency, and a gained understanding of how powerful JavaScript can be.  I've created a quick example I'd like to show you so that you can get the idea I was trying to communicate.

Let's say you have one host object with two child objects, both with get methods, and both do exactly the same task but with a different attribute:

var accessors = {
	sortable: {
		get: function() {
			return typeof this.getAttribute('sortable') != 'undefined';
		}
	},
	droppable: {
		get: function() {
			return typeof this.getAttribute('droppable') != 'undefined';
		}
	}
};

Repeating the same code isn't ideal, so we could create one external function, passing it an attribute argument:

function getAttribute(attr) {
	return typeof this.getAttribute(attr) != 'undefined';
}
 
var accessors = {
	sortable: {
		get: function() {
			return getAttribute('sortable');
		}
	},
	droppable: {
		get: function() {
			return getAttribute('droppable');
		}
	}
};

That's a lot better but still not ideal because there's an extra, intermediate function execution every time the method is called.  What would work best is a function that returned the final function  -- that would eliminate the extra function execution with every call to get:

function generateGetMethod(attr) {
	return function() {
		return typeof this.getAttribute(attr) != 'undefined';
	};
}
 
var accessors = {
	sortable: {
		get: generateGetMethod('sortable')
	},
	droppable: {
		get: generateGetMethod('droppable')
	}
};

/* functional equivalent to the original code:

var accessors = {
	sortable: {
		get: function() {
			return typeof this.getAttribute('sortable') != 'undefined';
		}
	},
	droppable: {
		get: function() {
			return typeof this.getAttribute('droppable') != 'undefined';
		}
	}
};

*/

What you see above is a function returning a function; each method gets its own method for getting the property and there's no overhead upon each get call.

This is a really useful technique that saves you from repeating likewise code and, when used correctly, is easy to understand and maintain!

Recent Features

Incredible Demos

  • By
    External Site Link Favorite Icons Using MooTools and CSS

    I recently came upon an interesting jQuery article about how you can retrieve all external links within a page, build the address of the site's favorite icon, and place the favorite icon along side the link. I've chosen a different approach which...

  • By
    MooTools Equal Heights Plugin:  Equalizer

    Keeping equal heights between elements within the same container can be hugely important for the sake of a pretty page. Unfortunately sometimes keeping columns the same height can't be done with CSS -- you need a little help from your JavaScript friends. Well...now you're...

Discussion

  1. I know an old XHR implementation which checked against ActiveX and then returned an XHR handler, specifically for IE or other browsers. Something similar was implemented for event handlers. Modern libraries ought to have this behaviour all over the place. It’s actually a very useful every day technique.

  2. I really love it when you write short little helpful articles like this. Thanks for this technique!

  3. Nice example, with the added partial function as a hidden bonus :) Love JavaScript.

  4. Prince Shahnawaz

    awesome technique.. it might be very useful… ;)

  5. MaxArt

    Guys, this is where Javascript reveals all of its potential.
    Never be afraid to use it. Can save you a lot of code, way more what you can save using jQuery.

  6. John

    Hey, I have a noob question. Can’t you do the following?

    function getAttribute(attr) {
    	return typeof this.getAttribute(attr) != 'undefined';
    }
     
    var accessors = {
    	sortable: {
    		get: return getAttribute('sortable');
    	},
    	droppable: {
    		get: return getAttribute('droppable');
    	}
    };
    
    
    
    • Fahmi

      No, because a return statement must always be in a function.

  7. Chris

    Couldn’t you just bind the argument, rather than curry the function?

    • Carlos

      I think it is because you don’t want to return a value but a function so sortable.get or droppable.get are not values but functions to be called like this get()

  8. Vitor

    Thank you, this is also a very interesting feature when creating an array of methods, such as cpu emulators.

  9. Terrific explanation. Thank you for the question, John, and reply, Carlos.

  10. Jmaxsin

    Can you do this?

    function createKey(kStr) {
        return function(k) {
    	if (k === null) {
                throw new Error("null is not a valid " + kStr);
    	} else if (k === UNDEFINED) {
    	    throw new Error(kStr + " must not be undefined");
    	}
         };
    }

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!