Poznajemy maybe monad w JavaScript. Lekcja łatwa, prosta i przyjemna. Do dzieła!

Tak wygląda Maybe Monad:

function Maybe(value) {
    this.value = value;
  }
  
Maybe.prototype.bind = function(transform) {
    return this.value === null || this.value === undefined ? this : new Maybe(transform(this.value));
  };

Maybe.prototype.valueOf = function(){
    return this.value;
}

Oto przykład użycia:

let password = "admin";

let passMaybe = new Maybe(password);

let passUpper = passMaybe.bind((pass) => pass.toUpperCase());

let hiddenPass = passMaybe.bind((pass) => "*".repeat(pass.length));

console.log(hiddenPass.valueOf());
//*****

console.log(passUpper.valueOf());
//ADMIN

Oczywiście mnoży obiekty, nie musimy tego chcieć. Zróbmy sobie coś na bazie tego:

function Selected(selector){
    this.el = document.querySelector(selector);
}

Selected.prototype.bind = function(transform){
    return this.el == null ? this : new Selected(transform(this.el));
}

window.addEventListener('DOMContentLoaded', function(){

    let para = new Selected("#para");

    para.bind((p) => {
        p.textContent = "";
    });
    
    para.bind((p) => {
        p.textContent = "new text";
    });
});

W naszym przypadku bardziej opłaca się, aby zwracało wynik funkcji niż tworzyło niepotrzebne referencje do tego samego elementu:

function Selected(selector){
    this.el = document.querySelector(selector);
}

Selected.prototype.bind = function(transform){
    return this.el == null ? this : transform(this.el);
}

window.addEventListener('DOMContentLoaded', function(){

    let para = new Selected("#para");
    let oldText = para.bind((p) => p.textContent);

    para.bind((p) => {
        p.textContent = "new text";
    })

    console.log(oldText);
    //bla bla bla
});