Created
July 2, 2012 20:41
-
-
Save cowboy/3035578 to your computer and use it in GitHub Desktop.
JavaScript: practical partial application, like creating a function that can be passed to Array#filter or the like.
This file contains hidden or 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
/* | |
* Function#filterify | |
* | |
* Copyright (c) 2012 "Cowboy" Ben Alman | |
* Licensed under the MIT license. | |
* http://benalman.com/about/license/ | |
*/ | |
Function.prototype.filterify = (function() { | |
// IIFE gives us a place for storing local vars... | |
var arraySlice = Array.prototype.slice; | |
// ...and keeps the local "filterify" NFE name from leaking in IEs. | |
return function filterify() { | |
var fn = this; | |
// "Pre" arguments. | |
var pre = arraySlice.call(arguments); | |
// "Post" arguments. | |
var post = []; | |
// Search the arguments for placeholder. | |
var idx = pre.indexOf(filterify); | |
// If placeholder was found, adjust both pre and post so that they | |
// are the arguments before and after the placeholder. | |
if (idx !== -1) { | |
post = pre.splice(idx, pre.length - idx).slice(1); | |
} | |
// The returned function will be passed to Array#filter or the like and | |
// should only accept one argument. | |
return function filterified(value) { | |
// Invoke the original function, inserting the passed-in value wherever | |
// the "filterify" placeholder was (or at the end). | |
return fn.apply(this, pre.concat(value, post)); | |
}; | |
}; | |
}()); |
This file contains hidden or 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
var foo = function(a, b, c) { | |
console.log(a, b, c); | |
}; | |
foo("a", "b", "c"); | |
// a b c | |
console.log("---"); | |
var __ = Function.filterify; // Placeholder reference | |
["_", "__", "___"].forEach(foo.filterify(__, "b", "c")); | |
// _ b c | |
// __ b c | |
// ___ b c | |
["_", "__", "___"].forEach(foo.filterify("a", __, "c")); | |
// a _ c | |
// a __ c | |
// a ___ c | |
["_", "__", "___"].forEach(foo.filterify("a", "b", __)); | |
// a b _ | |
// a b __ | |
// a b ___ | |
console.log("---"); | |
["_", "__", "___"].forEach(foo.filterify()); | |
// _ undefined undefined | |
// __ undefined undefined | |
// ___ undefined undefined | |
["_", "__", "___"].forEach(foo.filterify("a")); | |
// a _ undefined | |
// a __ undefined | |
// a ___ undefined | |
["_", "__", "___"].forEach(foo.filterify("a", "b")); | |
// a b _ | |
// a b __ | |
// a b ___ |
@jdalton, I started to do that but then decided on a whole different approach. I didn't test it, but I'd imagine the new way is significantly faster.
Good call. It's hard to keep track of method signatures when MDN also lists SpiderMonkey extensions.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Instead of slicing
arguments
just leave it unchanged and usemap.call
.