Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

Warning: This is a long post. Let\'s keep it simple. I want to avoid having to p

ID: 641886 • Letter: W

Question

Warning: This is a long post.

Let's keep it simple. I want to avoid having to prefix the new operator every time I call a constructor in JavaScript. This is because I tend to forget it, and my code screws up badly.

The simple way around this is this...

function Make(x) {
if ( !(this instanceof arguments.callee) )
return new arguments.callee(x);

// do your stuff...
}
But, I need this to accept variable no. of arguments, like this...

m1 = Make();
m2 = Make(1,2,3);
m3 = Make('apple', 'banana');
The first immediate solution seems to be the 'apply' method like this...

function Make() {
if ( !(this instanceof arguments.callee) )
    return new arguments.callee.apply(null, arguments);

// do your stuff
}
This is WRONG however -- the new object is passed to the apply method and NOT to our constructor arguments.callee.

Now, I've come up with three solutions. My simple question is: which one seems best. Or, if you have a better method, tell it.

First

Explanation / Answer

Firstly arguments.callee is deprecated in ES5 strict so we don't use it. The real solution is rather simple.

You don't use new at all.

var Make = function () {
if (Object.getPrototypeOf(this) !== Make.prototype) {
var o = Object.create(Make.prototype);
o.constructor.apply(o, arguments);
return o;
}
...
}
That's a right pain in the ass right?

Try enhance

var Make = enhance(function () {
...
});

var enhance = function (constr) {
return function () {
if (Object.getPrototypeOf(this) !== constr.prototype) {
var o = Object.create(constr.prototype);
constr.apply(o, arguments);
return o;
}
return constr.apply(this, arguments);
}
}
Now of course this requires ES5, but everyone uses the ES5-shim right?

You may also be interested in alternative js OO patterns

As an aside you can replace option two with

var Make = function () {
var that = Object.create(Make.prototype);
// use that

return that;
}
In case you want your own ES5 Object.create shim then it's really easy

Object.create = function (proto) {
var dummy = function () {};
dummy.prototype = proto;
return new dummy;
};