开发者

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

开发者 https://www.devze.com 2023-02-19 07:22 出处:网络
This is from John Resig`s Learning Advanced JavaScript #35 http://ejohn.org/apps/learn/#35 , calledWhat happens when we forget to use the new operator?

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." );


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.


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.


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.


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消