Last active
February 17, 2018 16:43
-
-
Save adityavm/11784b33e29e52fa72349f92e95b7de4 to your computer and use it in GitHub Desktop.
How to build properties that can be called or chained
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
/** | |
* Executors | |
* --- | |
* These perform the final action at each step of the chain. | |
*/ | |
const keys = Object.create(null); | |
keys.red = function(str) { return `red(${str})`; }, | |
keys.red.type = "red"; | |
keys.blue = function(str) { return `blue(${str})`; }; | |
keys.blue.type = "blue"; | |
keys.yellow = function(str) { return `yellow(${str})`; }; | |
keys.yellow.type = "yellow"; | |
/** | |
* Module | |
* --- | |
* This exports a module the properties of which can be chained or called. | |
*/ | |
// Initialise module | |
function Module(){}; | |
Module.q = []; | |
// Build chain | |
function Chain(q, key) { | |
// Calling this ends the chain | |
function execute(str) { | |
q.push(keys[key](str)); | |
return q.join(","); | |
} | |
// Otherwise add new value to chain, and pass on | |
execute.q = [...q, key]; | |
return execute; | |
} | |
// Define properties. Each property is callable, but also has | |
// a circular prototype to initial keys | |
const init = {}; | |
for(const key of Object.keys(keys)) { | |
init[key] = { | |
get(){ | |
const self = this; // keep context so the chain remains | |
function fn3(){ return Chain(self.q, key); } // add this call's properties in the chain | |
fn3.__proto__ = init; // create circular properties to allow chaining | |
return fn3(); // build a link in the chain | |
} | |
}; | |
} | |
Object.defineProperties(Module.__proto__, init); // Assign first layer of properties to module | |
module.exports = Module; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment