JSFiddle - React, Tailwind, and code Playground

by Alex Russell

HTML

<html>
    <body>
        <button id="b">Howdy!</button>
    </body>
</html>

JavaScript

"use strict";

//
// De-suagring
//
Object.defineProperty(
    Function.prototype,
    "prefer",
    {
        writable: true,
        enumberable: false,
        value: function(scope){
            var orig = this;
            var f = function() { return orig.apply(scope||this, arguments); };
            Object.defineProperty(f, "preferredScope", {
                value: scope, writable: false, enumerable: false,
            });
            // NOTE: I'm re-defining .call() and .apply() per function object 
            // here, but a spec'd version would simply re-define .call() and
            // .apply() to understand preferredScope and defer to them if no
            // scope is passed.
            Object.defineProperty(f, "call", {
                value: function() {
                    var callScope = arguments[0];
                    var args = Array.prototype.slice.call(arguments, 1);
                    return orig.apply(callScope||scope||this, args);
                },
                writable: true, enumerable: false,
            });
            Object.defineProperty(f, "apply", {
                value: function() {
                    var applyScope = arguments[0];
                    return orig.apply(callScope||scope||this, arguments[1]);
                },
                writable: true, enumerable: false,
            });
            return f;
        }
    }
);

//
// Example usage
//
var instance = {
    message: "May the force be with you.",
    logger: function() {
        console.log(this.message);
    }
};

var b = document.getElementById("b");
b.message = "It's a trap!!";
var logger = instance.logger.prefer(instance);
b.addEventListener("click", logger, false);

logger.call({ message: "History repeating."});