-
-
Save matt-mcmahon/2f685c21fbbd68251dba704564b8f0e4 to your computer and use it in GitHub Desktop.
Method Binding Is An Implicit Part Of Your API Contract (Whether You Like It Or Not)
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
// Require the core node modules. | |
var chalk = require( "chalk" ); | |
// ----------------------------------------------------------------------------------- // | |
// ----------------------------------------------------------------------------------- // | |
// I am a mock zEmbed class. | |
// -- | |
// NOTE: With a traditional "class", all of the internal references use "this" because | |
// the methods are all located on the class prototype and do not have a lexical binding | |
// to any of the other methods or instance variables. | |
class ZEmbed { | |
constructor( token ) { | |
this.token = token; | |
} | |
// --- | |
// PUBLIC METHODS. | |
// --- | |
hide() { | |
console.log( chalk.red( `Hiding widget ${ this.token }.` ) ); | |
// Return this object to facilitate method chaining. | |
return( this ); | |
} | |
show() { | |
console.log( chalk.green( `Showing widget ${ this.token }.` ) ); | |
// Return this object to facilitate method chaining. | |
return( this ); | |
} | |
} | |
// ----------------------------------------------------------------------------------- // | |
// ----------------------------------------------------------------------------------- // | |
var zEmbed = new ZEmbed( "9cf6672aaf" ); | |
// Let's detach the methods from the object for extra clarity on binding. | |
var show = zEmbed.show; | |
var hide = zEmbed.hide; | |
// Because the zEmbed methods are part of a traditional class bindings, the following | |
// calls WILL BREAK. The methods are being executed outside of their expected context. | |
setTimeout( show, 500 ); | |
setTimeout( hide, 1000 ); |
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
// Require the core node modules. | |
var chalk = require( "chalk" ); | |
// ----------------------------------------------------------------------------------- // | |
// ----------------------------------------------------------------------------------- // | |
// I am a mock zEmbed object constructor. | |
function ZEmbed( token ) { | |
// Return the public API for this object. | |
// -- | |
// NOTE: The public API is a collection of functions that are using lexical binding | |
// in order to locate "class variables". | |
return({ | |
hide: hide, | |
show: show | |
}); | |
// --- | |
// PUBLIC METHODS. | |
// --- | |
function hide() { | |
console.log( chalk.red( `Hiding widget ${ token }.` ) ); | |
} | |
function show() { | |
console.log( chalk.green( `Showing widget ${ token }.` ) ); | |
} | |
} | |
// ----------------------------------------------------------------------------------- // | |
// ----------------------------------------------------------------------------------- // | |
var zEmbed = new ZEmbed( "9cf6672aaf" ); | |
// Let's detach the methods from the object for extra clarity on binding. | |
var show = zEmbed.show; | |
var hide = zEmbed.hide; | |
// Because the zEmbed methods are using lexical binding, the methods can be passed | |
// around as "naked" references. This feature is an IMPLICIT part of your object API. | |
setTimeout( show, 500 ); | |
setTimeout( hide, 1000 ); |
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
// Require the core node modules. | |
var chalk = require( "chalk" ); | |
// ----------------------------------------------------------------------------------- // | |
// ----------------------------------------------------------------------------------- // | |
// I am a mock zEmbed object constructor. | |
function ZEmbed( token ) { | |
// Return the public API for this object. | |
// -- | |
// NOTE: The public API is a collection of functions that are using lexical binding | |
// in order to locate "class variables". However, the public method do return a | |
// reference back to the public API (this) for method chaining. | |
return({ | |
hide: hide, | |
show: show | |
}); | |
// --- | |
// PUBLIC METHODS. | |
// --- | |
function hide() { | |
console.log( chalk.red( `Hiding widget ${ token }.` ) ); | |
// Return this object to facilitate method chaining. | |
return( this ); | |
} | |
function show() { | |
console.log( chalk.green( `Showing widget ${ token }.` ) ); | |
// Return this object to facilitate method chaining. | |
return( this ); | |
} | |
} | |
// ----------------------------------------------------------------------------------- // | |
// ----------------------------------------------------------------------------------- // | |
var zEmbed = new ZEmbed( "9cf6672aaf" ); | |
// Let's detach the methods from the object for extra clarity on binding. | |
var show = zEmbed.show; | |
var hide = zEmbed.hide; | |
// Because the zEmbed methods are using lexical binding, the methods can be passed | |
// around as "naked" references. This feature is an IMPLICIT part of your object API. | |
setTimeout( show, 500 ); | |
setTimeout( hide, 1000 ); | |
// ----------------------------------------------------------------------------------- // | |
// ----------------------------------------------------------------------------------- // | |
// Even though the zEmbed class methods are using lexical binding to locate the class | |
// properties, they are also using the this-binding to return a reference back to the | |
// public API. This allows for method chaining, but ONLY IF you invoke the methods in | |
// the context of the public API. | |
setTimeout( | |
() => { | |
// Try method-chaining in the context of the API. | |
console.log( chalk.bold( "\n== Trying method chaining ==" ) ); | |
zEmbed.show().hide(); | |
// Try method-chaining with the naked method references. | |
console.log( chalk.bold( "\n== Trying NAKED method chaining ==" ) ); | |
show().hide(); | |
}, | |
2000 | |
); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment