Last active
December 23, 2015 06:49
-
-
Save mattfield/6596715 to your computer and use it in GitHub Desktop.
Explanation of a splat function for linking purposes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// splat is an abstraction that wraps around _.map, | |
// turning a function into a mapping | |
// NB: we're using Underscore/Lodash here because we | |
// want our mapping to work everywhere. You could | |
// easily replace this implementation with one | |
// that uses the native Array#map | |
function splat(fn){ | |
return function(list){ | |
_.map(list, fn); | |
} | |
} | |
// Suppose we have a simple but overly-specific function | |
// that grabs a list of DOM elements, maps over them | |
// and returns their text contents | |
function getNavParams(){ | |
_.map($('.nav-item'), function(element){ | |
return $(element).text(); | |
}); | |
} | |
getNavParams(); | |
//=> ["Home", "About", "Blog", "Shop"] | |
// This is very limited in scope and not very reusable. | |
// It could be better. | |
// | |
// What we're really interested in here is the body | |
// of the getElementParams function. Let's start | |
// by making it less element-specific | |
function getElementParams(el){ | |
_.map($(el), function(element){ | |
return $(element).text(); | |
}); | |
} | |
// Ok, so this is a bit better; it's no longer | |
// implementation-specific. However, we could | |
// abstract this further. Our mapping could be | |
// abstracted out into it's own function | |
// that takes an element and returns it's text | |
function getCurrentValue(el){ | |
return $(el).text(); | |
} | |
// Plugging that back in we get: | |
function getElementParams(el){ | |
_.map($('.nav-item'), getCurrentValue); | |
} | |
// This is a big improvement and arguably much more | |
// readable. With useful function names we can see | |
// that we're mapping the getCurrentValue function | |
// over a list of DOM elements. This gives us the | |
// same result as before: | |
getElementParams(); | |
//=> ["Home", "About", "Blog", "Shop"] | |
// But we can abstract this problem out even more. | |
// It's true that we may want to have a wrapper function | |
// that just grabs a list of values for a specific | |
// selector, and we certainly want to avoid having to | |
// rewrite our original get[something]Params function | |
// over and over with a different element each time. | |
// Let's use `splat` to create a single, reusable function | |
// that uses `getCurrentValue`: | |
var getParams = splat(getCurrentValue); | |
// Now what we have is a partially-applied mapping function | |
// that does the same thing as above. All it's waiting for | |
// is a list to operate on | |
var navParams = getParams($('.nav-item')); | |
navParams; | |
//=> ["Home", "About", "Blog", "Shop"] | |
var ingredients = getParams($('li.ingredient')); | |
ingredients; | |
//=> ["Milk", "Sugar", "Butter"] | |
// How about another use for `splat`. We'll use another small | |
// function, `get` that takes the name of a property and | |
// returns a function that gets that property from an object | |
function get(attr){ | |
return funtion(object){ | |
return object[attr]; | |
} | |
} | |
var ingredients = { | |
"milk": "300ml", | |
"sugar": "200g", | |
"butter": "3tbsp" | |
}; | |
get('milk')(ingredients); | |
//=> "300ml" | |
// Let's make our data structure a bit more high-level | |
// and make use of splat | |
var recipes = [ | |
{ "milk": "300ml", "sugar": "200g", "butter": "3tbsp" }, | |
{ "milk": "120ml", "sugar": "100g", "butter": "1tbsp" }, | |
{ "milk": "1 pint", "sugar": "2 cups", "butter": "300g" } | |
]; | |
splat(get('milk'))(recipes); | |
//=> ["300ml", "120ml", "1 pint"] | |
// That's way nicer than doing the same thing "longhand" | |
// like this: | |
// | |
// splat(function(recipe){ return recipe.milk })(recipes); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment