Reputation: 319
function Person(name, age, gender) {
this.name = name; // run
}
function PersonSafe(name) {
if (!(this instanceof arguments.callee))
return new PersonSafe(name)
this.name = name; // run
}
var qux = Person('qux');
console.log('Person qux: ', qux);
console.log('[[global]] name: ', name);
var quxSafe = PersonSafe('qux');
console.log('PersonSafe qux: ', quxSafe);
A comparison of the two situations when the constructor
is called without the new
keyword.
I don't know why the results of running the two codes are different.
The body
ofPerson()
andPersonSafe()
functions are different,
but the line (this.name = name;
) thatqux
and quxSafe
will execute is the same.
So... Why are the results different?
Upvotes: 0
Views: 66
Reputation: 370879
When you call a function as a constructor (here, Person
), an object is created (an empty object whose internal prototype is the constructor function's prototype - Person.prototype
here), and that object that was just created is what the this
value will point to inside the function. That object will also be implicitly returned at the end of the constructor.
In contrast, when you don't use new
, no such object is created; you're just calling an ordinary function, and the this
value inside it will depend on the calling context of the function. Here, because there's no calling context (the function being called is not part of an object), the this
inside the function will either be the global object (in the case of sloppy mode), or undefined
(in the case of strict mode).
So var qux = Person('qux');
runs this.name = name
, where this
is the global object.
With PersonSafe
, you're checking that the this
is an instance of the constructor (that the this
has an internal prototype of the constructor's prototype) - if called without new
, that test will fail, since this
will be either the global object or undefined
.
Note that arguments.callee
is forbidden in strict mode, and strict mode should nearly always be used. Consider replacing with new.target
instead:
function PersonSafe(name) {
if(!(new.target))
return new PersonSafe(name)
this.name = name; // run
}
var quxSafe = PersonSafe('qux');
console.log('PersonSafe qux: ',quxSafe);
Upvotes: 2
Reputation: 225
The main reason why this is different is caused by "new" keyword which means that function will be treated as object and it will get proto property assigned.
Also this variable will be pointed to newly created object.
Here is good description: What is the 'new' keyword in JavaScript?
Upvotes: 1