15

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: ...
    }
}();
Dan Dascalescu
  • 143,271
  • 52
  • 317
  • 404
Raynos
  • 166,823
  • 56
  • 351
  • 396
  • exact duplicate of [Is it right to think of a Javascript Function Expression that uses the 'new' keyword as 'static'](http://stackoverflow.com/q/10406552/1048572) - except for the question in the title – Bergi Sep 17 '14 at 15:14
  • For the title question, see [JavaScript: How does 'new' work internally](http://stackoverflow.com/q/6750880/1048572) – Bergi Sep 17 '14 at 15:15

2 Answers2

17

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
  • 337,827
  • 72
  • 505
  • 443
  • 2
    Now I only have to figure out what this.prototype, this.apply & Function.method do internally :). Sometimes I feel I should just assume and hack around more and try to understand internals less. – Raynos Sep 06 '10 at 12:03
  • @Raynos: `Function.method` is not a built-in method. Added some further info on this. – Daniel Vassallo Sep 06 '10 at 12:09
  • Thank you, I will take some time to read those in the future. Still getting the hang of prototyping. – Raynos Sep 06 '10 at 12:18
  • 1
    Seems that Mr. Crockford forgot that functions are also objects hehe (it will still return `that` if `other` is a function) – Christian C. Salvadó Sep 07 '10 at 23:32
  • @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 Sep 08 '10 at 00:05
  • @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*). – Christian C. Salvadó Sep 08 '10 at 00:22
  • ... I think [this](http://jsbin.com/ipipa3/edit) example can express exactly what I mean ;) – Christian C. Salvadó Sep 08 '10 at 00:22
  • @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 Sep 08 '10 at 00:40
6

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
  • 318,141
  • 75
  • 454
  • 536