3

When considering this simple example

<script>

function test()
{
 this.x = 10;
}

var obj = new test();
</script>

I read in on one of the blogs that when we use a new keyword , a proto object would be created and "this" would be set to proto object. So, when I just call var obj = test(); , will the "this" be set to proto object or will the proto object not created at all in this scenario? So, what would be the basic difference from a programmer's point of view between the two calling methods?

user5283721
  • 607
  • 6
  • 16
  • 2
    Without `new` keyword, you are just invoking test function and in that case, `obj` will be undefined as `test()` does not return any value... – Rayon Feb 09 '16 at 04:12
  • There are a million questions here about the *new* operator and constructors called as functions. But maybe [*MDN*](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/new) will help. – RobG Feb 09 '16 at 04:39

3 Answers3

4
var obj = new test();

this would set x= 10 in the context of 'obj' only. That means after above statement if you do

console.log(obj.x); //output will be 10
console.log(x) //output will be error

Now, when you do:

var obj = test();

this would set x=10 in the execution context (global prototype). That means after above statement if you do:

console.log(obj.x); //output will be error
console.log(x) //output will be 10
Savaratkar
  • 1,974
  • 1
  • 24
  • 44
  • "*this would set x=10 in the execution context (global prototype)*". What? The global execution context is an environment, it doesn't have a prototype, nor does the global object have a prototype (or internal `[[Prototype]]`). – RobG Feb 09 '16 at 04:36
  • @RobG Usually every object (except the ones derived from `null` (because `null` has no prototype)) has a prototype, no matter the object context. See [this](http://stackoverflow.com/questions/32262809/is-it-bad-practice-to-use-object-createnull-versus/32262852#32262852) post and [this](http://adripofjavascript.com/blog/drips/creating-objects-without-prototypes.html) article. – Vidul Feb 09 '16 at 05:07
  • There is no "object context", nor any global prototype. Assigning to an undeclared, or otherwise "uncreated" variable, creates a property of the global object. There is no prototype involved. – RobG Feb 09 '16 at 08:38
  • For the sake of this question, when you do 'var obj = test();', it will attach 'x' property to 'window' object. – Savaratkar Feb 09 '16 at 09:17
2

I read in on one of the blogs that when we use a new keyword , a proto object would be created and "this" would be set to proto object.

If that's what it said, it was wrong.

If the new operator is used when calling a function, the function's this parameter is set to a new Object created as if by new Object(). This object has its internal [[Prototype]] set to the constructor's public prototype object.

It also causes the function to return this new object (and instance of the constructor) if no other object is returned by a return statement, so:

function test() {
  this.x = 10;
}
var obj = new test();

Creates a new object with a public x property with value 10 and internal [[Prototoype]] property that references test.prototype. A reference to this new object is assigned to obj.

So, when I just call var obj = test(); , will the "this" be set to proto object or will the proto object not created at all in this scenario?

You mean like:

var obj = test();

In this case, test is called without setting its this, so it will default to the global object (or be undefined in strict mode), so that:

this.x = 10;

creates an x property of the global object (if it didn't already exist) and assigns it the value of 10. This effectively creates a global variable, with subtle differences to one created using a variable declaration in the global execution context.

RobG
  • 142,382
  • 31
  • 172
  • 209
  • 1
    It would be nice if down voters said why the did so, then the answer might be improved. – RobG Feb 09 '16 at 08:34
1

The new statement creates a new instance (object) which basically inherits from the constructors prototype. However, the function's prototype (__proto__ in most environments) has nothing to do with the instances' prototype. If not used as a constructor (i.e. without new), the function will use different object context, in this case the global one (in hosting environments like the web browsers, this would be window). From MDN:

var o = new Object();

o.[[Prototype]] = Foo.prototype;

About the object context: more details. About the prototype and functions: more details.

Update In relation to the Rob's comment below: context and scope are not the same. Every function invocation has both a scope and a context associated with it. Fundamentally, scope is function-based while context is object-based. In other words, scope pertains to the variable access of a function when it is invoked and is unique to each invocation. Context is always the value of the this keyword which is a reference to the object that “owns” the currently executing code. (More details here.)

Vidul
  • 10,128
  • 2
  • 18
  • 20
  • "*…the function will use different object context, in this case the global one…*" a function's execution context is lexical and invariable, the value of its *this* parameter is not (except for broad arrow functions). – RobG Feb 09 '16 at 04:34
  • @RobG What do you imply by your statement? _Inside a function, the value of `this` depends on how the function is called._ (from MDN). That was my point. – Vidul Feb 09 '16 at 04:47
  • The phrase "object context" is confusing. Every execution context has a *this* parameter that references an object (or any value in strict mode). The value of *this* is usually set by how the function is called. The execution context is actually very closely related to scope, since it forms a kind of object with variables as properties that sits on the scope chain. I'm just commenting on the expression. – RobG Feb 09 '16 at 08:33
  • @RobG Again: see my update in the post, you seem to misuse the terms. – Vidul Feb 09 '16 at 11:08