Search code examples
javascriptnode.jssyntaxchainingchalk

How does NodeJS module, Chalk's, chaining syntax work?


I don't understand how Chalk's (NodeJS module) syntax works (and it bothers me). I have searched far and wide for an answer, but I am not having any luck and likely don't know the technical term(s) for what I need to look for. I have tried looking up chalk-specific questions here on StackOverflow, "method chaining", "prototypes", etc. Tried looking at Chalk's source code, but still can't seem to figure out my answer. The syntax in question is:

// Code snippet from the Chalk NPM Page.
log(chalk.blue.bgRed.bold('Hello world!'));
log(chalk.blue('Hello', 'World!', 'Foo', 'bar', 'biz', 'baz'));

I am familiar with method chaining and familiar with storing a function in an object. The main question I have is: how can chalk.blue be a property and a function at the same time?

Any help would be greatly appreciated. Whether it is a full explanation or a push in the right direction.


Solution

  • Chalk is probably using getters and setters to "call" the appropriate functions. The following is a simple example of what's going on:

    let a = function (txt) {
        console.log(a.buffer + txt);
        a.buffer = ''
    }
    
    a.buffer = '';
    
    Object.defineProperty(a,'b',{
        get: function(){
            this.buffer += '<B>';
            return this
        }
    });
    
    Object.defineProperty(a,'c',{
        get: function(){
            this.buffer += '<C>';
            return this
        }
    });
    
    Object.defineProperty(a,'d',{
        get: function(){
            this.buffer += '<D>';
            return this
        }
    });
    

    Basically it's just regular method chaining but using getters to make it fancy! Another trick is to make the base object a Function instead of a regular object so that the this you return becomes callable.

    Now you can do:

    a.b.c.b.d('hello'); // prints <B><C><B><D>hello