-
-
Save dschinkel/4b0b70011e33c6c0292c2e6302c7d69a to your computer and use it in GitHub Desktop.
Polymorphic functions and multiple dispatch in JavaScript
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
var args = [].slice.call(arguments, 0); |
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 () { | |
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 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 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 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 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 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' ] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment