redchicken
redchicken

Reputation: 319

Comparison of the two situations when the constructor is called without the new keyword

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

enter image description here

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

Answers (2)

CertainPerformance
CertainPerformance

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

Harion
Harion

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

Related Questions