mjmitche
mjmitche

Reputation: 2067

Using "new" in constructors, John Resig`s #35

This is from John Resig`s Learning Advanced JavaScript #35 http://ejohn.org/apps/learn/#35 , called What happens when we forget to use the new operator?

So he`s telling us that name variable (which I assume is window.name) gets overridden, but

1) is that overriding done inside the function User i.e. does this.name set a new global value for name?

2) how would have using "new User" (i.e. a constructor?) prevented overriding the window.name variable? is it because "new User" would only be an instance of User, but window.name is global?

Thanks if you can help explain.

function User(first, last){ 
  this.name = first + " " + last; 
} 

window.name = "Resig"; 
var user = User("John", name); 

assert( name == "John Resig", "The name variable is accidentally overridden." );

Upvotes: 1

Views: 368

Answers (4)

RobG
RobG

Reputation: 147413

When a function is called with the new operator, its this keyword is set to reference a new object whose internal [[prototype]] property is a reference to the constructor's public prototype.

When the function is called as a constructor (i.e. with the new keyword):

  this.name = ...

adds a name property to that new object and assigns it a vaule. Also, by default the function will return that new object to the caller.

If you omit new when calling the function, then its this keyword is a reference to the global object, so the line above assigns the value on the RHS to a name property of the global object.

However, it's a pretty easy error to spot since the function will return undefined. As soon as the variable that was supposed to refer to an instance of User is used for just about anything, it will throw a hard to miss error and likely end script execution right there.

So from the example:

function User(first, last) {
  this.name = first + " " + last;
}
var fred = User('fred','smith');
alert(fred.name);  // Error: fred is undefined

So yes, forgetting to use new can be a problem but it's not really that big an issue as constructors aren't that widely used, the module pattern is sufficient for most things.

Upvotes: 1

user578895
user578895

Reputation:

The short of it is this: If you use new, this refers to a new object. If you don't use new, this refers to window

So this.name is equivalent to window.name if new is not used.

Upvotes: 1

Felix Kling
Felix Kling

Reputation: 816600

Calling User() without new makes this inside the function refer to the global object, which is window in browsers. Therefore, the name property of the window object is overridden. Also note that user will contain the value undefined as the function does not return a value.

If the function is called with new, this will refer to an empty object which inherits from User.prototype. window.name stays untouched and the name property of the empty object is set instead. This new object is also implicitly returned by the function, so user will refer to it.

Upvotes: 3

Avilo
Avilo

Reputation: 1204

Because new was not used, the code called the function called User which set the global object's name property to a different value than it currently was. This would cause a potentially hard to track down bug in the code. As for point 2 you are correct, as the window object contains the 'global' namespace.

Upvotes: 1

Related Questions