Ben Nadel
On User Experience (UX) Design, JavaScript, ColdFusion, Node.js, Life, and Love.
I am the chief technical officer at InVision App, Inc - a prototyping and collaboration platform for designers, built by designers. I also rock out in JavaScript and ColdFusion 24x7.
Meanwhile on Twitter
Loading latest tweet...
Ben Nadel at CFUNITED 2010 (Landsdown, VA) with:

Providing A Return Value In A JavaScript Constructor

By Ben Nadel on

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.




Reader Comments

I think the basic rule is that if you return an object, that is used. Otherwise, the constructed object is.

Reply to this Comment

@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.

Reply to this Comment

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?

Reply to this Comment

@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:

  • function Singleton() {
  •  
  • if ( Singleton.instance ) {
  • return( Single.instance );
  • }
  •  
  • return( Singleton.instance = this );
  •  
  • }

This way, no matter how many times you call "new Singleton()", the class always returns the same instance.

Reply to this Comment

Post A Comment

You — Get Out Of My Dreams, Get Into My Comments
Live in the Now
Oops!
Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.