Created
June 24, 2011 08:05
-
-
Save ericelliott/1044413 to your computer and use it in GitHub Desktop.
Polymorphic functions and multiple dispatch in JavaScript
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 args = [].slice.call(arguments, 0); |
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 () { | |
var methods = { | |
init: function (args) { | |
console.log('initializing...'); | |
return this; | |
}, | |
hello: function (args) { | |
console.log('Hello, ' + args); | |
return this; | |
}, | |
goodbye: function (args) { | |
console.log('Goodbye, ' + args); | |
return this; | |
} | |
}; | |
function myModule(options) { | |
var args = [].slice.call(arguments, 0), | |
initialized = false, | |
action = 'init'; // init will run by default | |
if (typeof options === 'string' && | |
typeof methods[options] === 'function') { | |
action = options; | |
args.shift(); | |
} | |
return methods[action].apply(this, args); | |
} | |
myModule(); // initializing... | |
myModule('hello', 'world!'); // Hello, world! | |
myModule('goodbye', 'cruel world!'); // Goodbye, cruel world! | |
// We're just chaining the global object here, but jQuery is a good example | |
// of what's possible... | |
myModule('hello', 'chaining!') | |
.console.log('Function polymorphism and method dispatch are easy.'); | |
}()); |
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 morph(options) { | |
var args = [].slice.call(arguments, 0), | |
animals = 'turtles'; // Set a default | |
if (typeof options === 'string') { | |
animals = options; | |
args.shift(); | |
} | |
console.log('The pet store has ' + args + ' ' + animals); | |
} | |
morph('cats', 3); // The pet store has 3 cats | |
morph('dogs', 4); // The pet store has 4 dogs | |
morph(2); // The pet store has 2 turtles |
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 sort() { | |
var args = [].slice.call(arguments, 0); | |
console.log(args.sort()); // Prints [ 'a', 'b', 'c' ] | |
console.log(args.shift(), args); // Prints a [ 'b', 'c' ] | |
} | |
sort('b', 'a', 'c'); |
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 () { | |
function sort() { | |
// arguments is an array-like object, but it's missing useful array | |
// functions. We can instantiate a real array, and delegate a call to | |
// the the slice method to it. | |
// Notably, this is both shorter and faster than the commonly used | |
// Array.prototype.slice.call approach. | |
// Slice is an easy way to shallow-copy an array (or in this case, an | |
// array-like object). | |
var args = [].slice.call(arguments, 0); | |
// Now that args is a real array, we can use the sort method to sort the | |
// contents. Yay! | |
console.log(args.sort()); // Prints [ 'a', 'b', 'c' ] | |
// This is really handy to grab the first argument off the stack: | |
console.log(args.shift(), args); // Prints a [ 'b', 'c' ] | |
} | |
sort('b', 'a', 'c'); | |
// One common use of this pattern is to change the behavior of a function | |
// depending on what gets passed into it. This is called a polymorphic | |
// function: | |
function morph(options) { | |
var args = [].slice.call(arguments, 0), | |
animals = 'turtles'; // Set a default | |
if (typeof options === 'string') { | |
animals = options; | |
args.shift(); | |
} | |
console.log('The pet store has ' + args + ' ' + animals); | |
} | |
morph('cats', 3); // The pet store has 3 cats | |
morph('dogs', 4); // The pet store has 4 dogs | |
morph(2); // The pet store has 2 turtles | |
}()); | |
/* This gets really interesting in the context of a module. | |
* | |
* The goal is to expose a public api for a chainable | |
* module. If the module is part of a larger framework, | |
* you might not want to clutter the framework namespace | |
* with all your module's public methods. Using multiple | |
* dispatch, we can call methods by passing the method | |
* name as the first parameter. | |
* | |
* This is a great pattern for jQuery plugins: | |
*/ | |
(function () { | |
var methods = { | |
init: function (args) { | |
console.log('initializing...'); | |
return this; | |
}, | |
hello: function (args) { | |
console.log('Hello, ' + args); | |
return this; | |
}, | |
goodbye: function (args) { | |
console.log('Goodbye, ' + args); | |
return this; | |
} | |
}; | |
function myModule(options) { | |
var args = [].slice.call(arguments, 0), | |
initialized = false, | |
action = 'init'; // init will run by default | |
if (typeof options === 'string' && | |
typeof methods[options] === 'function') { | |
action = options; | |
args.shift(); | |
} | |
return methods[action].apply(this, args); | |
} | |
myModule(); // initializing... | |
myModule('hello', 'world!'); // Hello, world! | |
myModule('goodbye', 'cruel world!'); // Goodbye, cruel world! | |
// We're just chaining the global object here, but jQuery is a good example | |
// of what's possible... | |
myModule('hello', 'chaining!') | |
.console.log('Function polymorphism and multiple dispatch are easy.'); | |
}()); |
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
console.log(args.shift(), args); // Prints a [ 'b', 'c' ] |
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
console.log(args.sort()); // Prints [ 'a', 'b', 'c' ] |
Great example but one thing to note is that the use of polymorphic functions is discouraged in Node because they cannot be optimized by V8.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is a great example. I have been trying to find an description of polymorphic functions and or method multi dispatch.