Can you create functions with custom prototypes in JavaScript?

It is a tricky thing indeed, more complicated than it should be if the language was designed well…

Basically, you just can’t do it cleanly in current versions. Objects other than functions can not be callable.

In future Javascript versions, you can do it with a “proxy” object that can define a “call” handler. But it is still way too complicated and contrived in my opinion.

Another way to go about it is to make your object a real function, not a custom object. Then try to set its __proto__, which is non-standard yet but works in most modern browsers, except Opera and IE 8 or less. Also maybe set its constructor property for faking instanceof checks… such hacks are quite tricky though and results will vary a lot with environments.

The following example works fine on my Firefox:
http://jsfiddle.net/Q3422/2/

function MyFun() {
    if (!this || this==window) {
        return new MyFun();
    }

    var f = function() {
        return "thanks for calling!";
    }
    f.__proto__ = MyFun.prototype;
    f.constructor = MyFun;

    return f;
}

MyFun.prototype = {
    foo: function() {
        return "foo:" + this();
    },
    __proto__: Function.prototype
};

var f = new MyFun();
alert("proto method:"+f.foo()); // try our prototype methods
alert("function method:"+f.call()); // try standard function methods
alert("function call:"+f()); // try use as a function
alert('typeof:' + typeof f); // "function", not "object". No way around it in current js versions
alert('is MyFun:' + (f instanceof MyFun)); // true
alert('is Function:' + (f instanceof Function)); // true

Just wanted to add that you should not be worried about “copying” functions to each instance of your objects. The function itself is an object, so is never really copied, nor is it recompiled or anything. It does not waste memory, except for the function object reference itself and any closure variables.

Iterating over the prototype to copy it should not concern you as well, I guess you will not have a gazillion methods.

So your own last solution is probably the best if you need to support environments where proto is not settable, and you are not worried that your prototype might get extended after some objects already got created and they may not pick up the changes.

Leave a Comment