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.
精彩评论