Search code examples
javascriptinheritancefunctional-programminginstanceof

What would be the equivalent of `instanceof` when using functional inheritance?


In JavaScript there's a pattern to achieve inheritance called "Functional inheritance" described in chapter 5 of Crockfords "JavaScript: the good parts".

One of the disadvantages of the pattern -- as compared to using the pseudo-classical pattern -- is that we lose the ability to distinguish types using the instanceof operator.

Is there any way to achieve the same goal? How can we know that two objects are somehow related because they are of the same parent/base "type"?

Also how can we tell even though they are descendants of the same type they are different types themselves?

I don't know if not being able to use instanceof is a big loss but it doesn't seem like it is.

Notes

For those who are not familiar with Crockford's explanation, you can see an example at: JSFiddle, taken from here.


Solution

  • The instanceof operator is not special. You can implement it yourself as explained on the Mozilla Developer Network. See the accepted answer to the following question for more details:

    JavaScript inheritance and the constructor property

    Here's how the instanceof operator can be implemented in JavaScript:

    function instanceOf(object, constructor) {
        while (object != null) {
            if (object == constructor.prototype) { //object is instanceof constructor
                return true;
            } else if (typeof object == 'xml') { //workaround for XML objects
                return constructor.prototype == XML.prototype;
            }
            object = object.__proto__; //traverse the prototype chain
        }
        return false; //object is not instanceof constructor
    }
    

    Want to implement instanceOf for functional inheritance? That's easy to do too:

    var object = child({ name: "a functional object" });
    
    alert(object.instanceOf(child)); // true
    alert(object.instanceOf(base));  // true
    alert(object.sayHello());        // Hello, I'm a functional object
    
    function base(spec) {
        var that = {};
        that.name = spec.name;
        that.constructors = [base];
        that.instanceOf = instanceOf;
        return that;
    }
    
    function child(spec) {
        var that = base(spec);
        that.sayHello = sayHello;
        that.constructors.push(child);
        return that;
    
        function sayHello() {
            return "Hello, I'm " + this.name;
        }
    }
    
    function instanceOf(constructor) {
         return this.constructors.indexOf(constructor) >= 0;
    }

    Of course, in real functional programming there's no need to use instanceof at all.