Providing A Return Value In A JavaScript Constructor
In my post yesterday, on using Base Controllers in AngularJS, I was able to leverage a funky-fresh feature of the JavaScript language: returning explicit values from a Constructor function. Most of the time, Constructor functions either return "this," or they omit the return statement altogether. However, if you do provide an explicit return statement, it may significantly change the reference returned to the calling context.
To explore this, I set up a number of JavaScript constructor functions that each provide a different, explicit return value. The result of the constructor instantiation is then logged to the console:
<!doctype>
<html>
<head>
<meta charset="utf-8" />
<title>Providing A Return Value In A JavaScript Constructor</title>
</head>
<body>
<h1>
Providing A Return Value In A JavaScript Constructor
</h1>
<script type="text/javascript">
// Undefined return value.
function A() {
return;
}
// Reference to instance.
function B() {
return( this );
}
// String return value.
function C() {
return( "string" );
}
// Number retun value.
function D() {
return( 123 );
}
// New object return value.
function E() {
return( { foo: "bar" } );
}
// New array return value.
function F() {
return( [ "foo", "bar" ] );
}
// New instantiation return value.
function G() {
return( new A() );
}
// Native "object" return value -- this one would be the same
// for Number, Boolean, and String.
function H() {
return( new Number( 123 ) );
}
// -------------------------------------------------- //
// -------------------------------------------------- //
// See what reference we have as a result of instantiation.
console.log( new A() );
console.log( new B() );
console.log( new C() );
console.log( new D() );
console.log( new E() );
console.log( new F() );
console.log( new G() );
console.log( new H() );
</script>
</body>
</html>
When I run the above code, I get the following console output:
A {}
B {}
C {}
D {}
Object { foo="bar"}
["foo", "bar"]
A {}
Number {}
As you can see, the first four invocations return the constructor instantiation to the calling context. But, when you start returning explicit, complex objects and arrays in a constructor function, you completely override the reference that is returned to the calling context.
This is an odd feature of the language, but it's not unique; I'm pretty sure that ColdFusion also provides similar behavior. That said, it is a nifty feature of the language that can really do some awesome stuff.
Want to use code from this post? Check out the license.
Reader Comments
I think the basic rule is that if you return an object, that is used. Otherwise, the constructed object is.
@Alex,
Correct - this is why a return value of "123" is ignored; but, a return value of Number( 123 ) is used. The latter returns a complex object, not a simple value.
I can possibly see this as a way to create an object that lets you use the "new Something()" syntax as a constructor but allows "private" methods through encapsulation, but what other use-cases would you have?
Nice article. The full documentation of the 'new' operator and how it relates to functional prototypes provides a detailed description of how the return value of the operator is used.
http://ecma262-5.com/ELS5_HTML.htm#Section_13.2.2
When you define a constructor like that "new" becomes redundant (as it should be).
@Jon,
The most recent place that I used this was to create a constructor that was actually a *factory* for a different type of object. Along those lines, I suppose you could use such a pattern to enforce a "singleton". So that no matter what, you only ever return a single, common reference to a given object. Something like:
This way, no matter how many times you call "new Singleton()", the class always returns the same instance.