views:

85

answers:

2

I am curious as what else the new keyword does in the background apart from changing what the this scope refers too.

For example if we compare using the new keyword to make a function set properties and methods on an object to just making a function return a new object is there anything extra that the new object does?

And which is preferred if I don't wish to create multiple objects from the function constructor

 var foo2 = function() {
  var temp = "test";

  return {
   getLol:
    function() {
     return temp;
    },

   setLol:
    function(value) {
     temp = value;
    }
  };

 }();

 var foo = new function() {
  var temp = "test";

  this.getLol = function() {
   return temp;
  }

  this.setLol = function(value) {
   temp = value;
  }
 }();

The firebug profiler tells me using the new keyword is slightly faster (2ms instead of 3ms), on large objects is new still significantly faster?

[Edit]

Another matter is on really large object constructors is having a return at the bottom of the function (It will have a large amount of local functions) or having a few this.bar = ... at the top of the function more readable? What is considered a good convention?

var MAIN = newfunction() {
    this.bar = ...

    // Lots of code
}();

var MAIN2  = function() {
    // Lots of code

    return {
        bar: ...
    }
}();
+2  A: 

Quoting Douglas Crockford from the Good Parts book (page 47), to answer the title of this question:

If the new operator were a method instead of an operator, it could be implemented like this:

Function.method('new', function () {

   // Create a new object that inherits from the 
   // constructor's prototype.

   var that = Object.create(this.prototype);

   // Invoke the constructor, binding -this- to
   // the new object.

   var other = this.apply(that, arguments);

   // If its return value isn't an object,
   // substitute the new object.

   return (typeof other === 'object' && other) || that;
});

The Function.method method is implemented as follows. This adds an instance method to a class (Source):

Function.prototype.method = function (name, func) {
   this.prototype[name] = func;
   return this;
};

Further reading:

Daniel Vassallo
Raynos
@Raynos: `Function.method` is not a built-in method. Added some further info on this.
Daniel Vassallo
Thank you, I will take some time to read those in the future. Still getting the hang of prototyping.
Raynos
Seems that Mr. Crockford forgot that functions are also objects hehe (it will still return `that` if `other` is a function)
CMS
@CMS: The constructor will only return a function when constructing a function with `new Function()`, right? In that case the above would not work, unless we check for `typeof other === 'function'` as well. Is that right, or am I missing something?
Daniel Vassallo
@Daniel, the [`[[Construct]]`](http://bclary.com/2004/11/07/#a-13.2.2) internal operation checks if the result of invoking the constructor function is *not* a primitive, if that's the case (an object was returned) that value is used as the result of the `NewExpression`. If you have a constructor that returns a function and you use the `new` operator on it, that function will be the result of the `NewExpression`, because the return value is not a primitive, is a function object. I would check something like [this](http://gist.github.com/528942) (see line *15*).
CMS
... I think [this](http://jsbin.com/ipipa3/edit) example can express exactly what I mean ;)
CMS
@CMS: Ok got it now... It's that the return value of the constructor can be explicitly overridden with the return statement, as in your jsbin example, returning a function... Thanks for the detailed explanation... I'll update my answer in a minute to reflect your comments :)
Daniel Vassallo
+1  A: 

Read the spec. Sections 11.2.2 and 13.2.2 are relevant and aren't too tricky to understand (note that the latter two links are to non-official HTML-ified version of the spec).

In summary, if you have a function f that returns an object, the only observable difference that calling it with new will make is that the this value will be different, and that calling it with new may be slower, since it involves additional steps of creating an object and assigning it a few properties.

Tim Down