What about this simple generic pattern (my favorite)?
(function(){ //IIF constructor builder
(this[arguments[0]]= function(/*args*/){ //The constructor
/*constructor payload code*/
}).prototype= { //Methods & Properties to inherit:
method_1: function(){ /*your code*/ } //method 1
, method_2: function(){ /*your code*/ } //method 2
, property_1: /*your code*/ //property 1
, property_2: /*your code*/ //property 2
};
})(/*constructor identifier*/);
this
will refer to the context where this build-function is run. So, if the constructor builder is run against the window
, then window
will have global function $elect
. So you can also use this pattern inside your modular system.
Update:
You have asked about
instanceof
(and judging by the code you supplied, you need it so one could omit
new
when calling your constructor).
This can make things a little bit more tricky.
To me personally, 'users' !== 'coders' and 'coders' (who write code (using x library) for users to use) should know when to use new
.
While it might be useful to throw new
/console.log
/alert
error during development, there should be no need for this in the final (minimized/optimized) production-code (unless your argument would be that you have a lot of new
statements that can be omitted, so your code can be minified even further).
First one must decide whether to optimize for
execution-speed and use of new
(code runs often?):
if(/*called with new*/){
/*constructor payload code*/
} else {
/*error code*/
}
or smallest filesize by lack of new
at cost of execution-speed (code runs just a couple of times? ):
if(!(/*called with new*/)){ /*error code*/ }
/*constructor payload code*/
note that the last option might also be more practical to comment-out/remove for production code if you intend to require the use of new
, giving the fastest execution-speed.
The line /*called with new*/
could be replaced with this instanceof arguments.callee
Although arguments.callee
is a nice generic solution (since nothing is hardcoded/named), it will throw an exception if you 'use strict';
-mode, since it is now deprecated (for some reason) in favor of named function expressions (and according to John Resig, one could also use the expression this function
in the future).
MDN specifies that a function name can be used only within the function's body, so for strict-mode we can name our (previously anonymous) function (C
in the following example)
and check if this instanceof C
(instead of this instanceof arguments.callee
):
(function(){ //IIF constructor builder
(this[arguments[0]]= function C(id){ //The constructor
if(!(this instanceof C)){ /*error code*/ } //Catch ID-10-T Error
/*constructor payload code*/
}).prototype= { //Methods & Properties to inherit:
method_1: function(){ /*your code*/ } //method 1
, method_2: function(){ /*your code*/ } //method 2
, property_1: /*your code*/ //property 1
, property_2: /*your code*/ //property 2
};
})('$elect');
If /*error code*/
only prevents a silent error by:
alert
/console.log
/throw new Error
('Error: forgot new')
then up until now this pattern (both strict and non-strict variant) is mind-numbingly generic.
If you want to 'fix' the call by returning the proper new object (besides the now optional warning to the coder) then one must think about the arguments (if any) that are passed to your constructor.
So for constructors that do not expect arguments, your /*error code*/
should contain:
return new arguments.callee();
for non-strict or
return new C();
for strict
Constructors that expect (optional) named arguments, your /*error code*/
should pass them hard-coded like:
return new arguments.callee(arg_1, arg_2 /*,etc..*/);
for non-strict or
return new C(arg_1, arg_2 /*,etc..*/);
for strict
As example:
(function(){ //IIF constructor builder
(this[arguments[0]]= function C(id){ //The constructor
if(!(this instanceof C)) return new C(id); //Fix ID-10-T Error
this.elm= document.getElementById(id);
}).prototype= { //Methods & Properties to inherit:
show: function(){ //Method show
this.elm.style.display= '';
}
, hide: function(){ //Method hide
this.elm.style.display= 'none';
}
, toggle: function(){ //Method toggle
this[this.elm.style.display ? 'show' : 'hide']();
}
};
})('$elect');
I am currently un-aware of a simple and elegant way to pass any (up to 256 for firefox) non-hardcoded unknown (expected/optional/named) arguments (short of one single array/object as first argument). The problem is that arguments
is an array(-like) object, so one can't simply pass it like return new C(arguments);
.apply()
to the rescue one might think, since it accepts an array of arguments as second argument (unlike .call()
that needs comma-separated arguments we were just trying to avoid), but alas: new
and apply
/call
can't be used together 1, 2... (Someone, please leave a comment if you know of an elegant solution that fits in this pattern, thank you)
Lastly a small variation (and possible application) to the above pattern. The main difference is that this pattern returns a constructor (so you can simply name the variable that references it) (instead of the above pattern that directly sets the constructor):
var myLibrary= {
$elect: (function(C){
(C= function(id){
if(!(this instanceof C)) return new C(id);
this.elm= document.getElementById(id);
}).prototype= {
addBorder: function(col){
this.elm.style.border='1px solid '+col;
}
, delBorder: function(){
this.elm.style.border='';
}
}; return C;
})()
, var_foo: 'foo'
, var_bar: 'bar'
};
Example fiddle here.
Hope this helps!