Created
September 13, 2011 11:29
-
-
Save cowboy/1213629 to your computer and use it in GitHub Desktop.
"IIFE" - It's like an IIFE, but BETTER!!! (??)
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
/*! | |
* "IIFE" - v0.2 - 9/14/2011 | |
* http://benalman.com/ | |
* | |
* Copyright (c) 2011 "Cowboy" Ben Alman | |
* Dual licensed under the MIT and GPL licenses. | |
* http://benalman.com/about/license/ | |
*/ | |
// Usage: | |
// | |
// IIFE([value, ...,] function([arg, ...]) { | |
// // your code goes here | |
// }); | |
function IIFE() { | |
// Because `arguments` is mutable, we can pop its last item off, leaving | |
// behind the remaining arguments to be passed into the passed function. | |
// Because `arguments` isn't an array however, Array#pop must be "borrowed" | |
// from Array.prototype, and executed using call invocation. | |
// | |
// To make a long story short: | |
// | |
// Invoke the last passed argument (function) in the same context as "IIFE," | |
// passing in all preceding arguments, and returning its value. | |
return Array.prototype.pop.call(arguments).apply(this, arguments); | |
} |
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
$(function() { | |
IIFE(1, 2, function(a, b, c) { | |
assert(a, 1, "should pass arguments correctly"); | |
assert(b, 2, "should pass arguments correctly"); | |
assert(c, undefined, "shouldn't pass the callback"); | |
}); | |
var obj = {} | |
IIFE.call(obj, 1, 2, function(a, b, c) { | |
assert(this, obj, "should set context arguments correctly"); | |
assert(a, 1, "should pass arguments correctly"); | |
assert(b, 2, "should pass arguments correctly"); | |
assert(c, undefined, "shouldn't pass the callback"); | |
}); | |
}); | |
// My "really simply unit testing framework" (note: requires jQuery) | |
function assert(actual, expected, message) { | |
var status = actual === expected | |
? "OK" | |
: "ERROR (got " + actual + ", expected: " + expected + ") " + message; | |
$("body").append(status + "<br/>"); | |
} |
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
// USAGE: EVERYDAY | |
// Gross! Those passed values are impossibly far away from the function's | |
// arguments list. In a large module, it would be very difficult to correlate $ | |
// and global with jQuery and this, without lots of scrolling or some kind of | |
// code folding or other magic. | |
(function($, global) { | |
console.log($.fn.jquery, global); | |
}(jQuery, this)); | |
// With "IIFE," passed values are right next to the function's arguments list, | |
// which makes the module much easier to understand! Note that the above pattern | |
// is called IIFE, so I've just made things all the more confusing. Of course, | |
// since you can use IIFEs and "IIFE" interchangeably, it should be ok. FWIW, | |
// this article describes the IIFE pattern, so read it if you're confused: | |
// http://benalman.com/news/2010/11/immediately-invoked-function-expression/ | |
IIFE(jQuery, this, function($, global) { | |
console.log($.fn.jquery, global); | |
}); | |
// USAGE: YOU CARE ABOUT `THIS` | |
var obj = {a: 123}; | |
// Same thing, except we're setting `this` inside the IIFE explicitly. It's | |
// even more gross than before! | |
(function($, global) { | |
console.log(this.a, $.fn.jquery, global); | |
}.call(obj, jQuery, this)); | |
// Same thing, except we're setting `this` inside the IIFE explicitly. See that | |
// everything you care about is all in one place. Awesome! | |
IIFE.call(obj, jQuery, this, function($, global) { | |
console.log(this.a, $.fn.jquery, global); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Very interesting! :)
Somehow I thought of AMD: group arguments to be passed into the function in an array (much like the moduleids in a require call).
function IIFE (args, func) {
return func.apply(this, args);
}
and then used:
IIFE([jQuery, this], function($, global) {
console.log($.fn.jquery, global);
});
There's a more logical grouping but the end results is not nearly as "scripty" though :D