Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can JavaScript constructor return function and keep inheritance?

function F() {
    return function() {
        return {};
    }
}

var f = new F();
f instanceof F; // returns false

As far as I understand, if I want instanceof to work, I need to return this from the constructor. But I want the constructor to return a function, and I cannot assign to this.

So, is this really impossible or can it be done somehow, for f = new F() to return a function and still f instanceof F to return true?

like image 902
Sixtease Avatar asked Apr 26 '12 20:04

Sixtease


People also ask

Are constructors inherited in JavaScript?

Conclusion. The constructor property is a piece of the inheritance mechanism in JavaScript.

Can you return in constructor JavaScript?

You shouldn't return anything in a constructor. A constructor is used to initialize the object. In case you want to know what happens is that if you return 5 then n will simply be an empty object and if you return for example { a: 5 } , then n will have a property a=5 .

What does constructor function return in JavaScript?

Usually, constructors do not have a return statement. Their task is to write all necessary stuff into this , and it automatically becomes the result. But if there is a return statement, then the rule is simple: If return is called with an object, then the object is returned instead of this .

Does JavaScript support multiple inheritance?

JavaScript does not support multiple inheritance, but mixins can be implemented by copying methods into prototype.


3 Answers

function F() {
    var r = function() {
        return {};
    };

    r.__proto__ = this.__proto__;
    return r;
}

var f = new F();
f instanceof F;
true
f();
Object

Only works in the browsers with __proto__

like image 62
Esailija Avatar answered Sep 21 '22 02:09

Esailija


You could of course make all functions appear to be instanceof F by setting F.prototype = Function.prototype;.

Unfortunately it looks as if ECMAScript doesn't allow you to create a function subclass.

You can however do it in Gecko using the deprecated __proto__ property:

function F() {
    function f() {
        return {};
    }
    f.__proto__ = F.prototype;
    return f;
 }
 F.prototype.__proto__ = F.__proto__;
like image 38
Neil Avatar answered Sep 20 '22 02:09

Neil


To anyone coming across this today, with ES6/2015 there's new syntax you can use to avoid the deprecated __proto__ property; Object.setPrototypeOf. Note that MDN warns that this is a slow/expensive operation.

function F() {
    const f = function() {
        return {};
    }
    Object.setPrototypeOf(f, F.prototype);
    return f;
}

var f = new F();
f instanceof F; // returns true
f(); // returns {}

Note also that it gets a little weird if you want to initialize values in the constructor. You need to set them as props on the function you will return, but later additions to the prototype will reference them as 'this'. e.g.

function F() {
    const f = function() {
        return {};
    }
    f.favoriteBand = 'The Books';
    Object.setPrototypeOf(f, F.prototype);
    return f;
}
F.prototype.getFavoriteBand = function(){ return this.favoriteBand; }

var f = new F();
f.getFavoriteBand() // returns 'The Books'
like image 30
igmcdowell Avatar answered Sep 24 '22 02:09

igmcdowell