2

I was just playing with JavaScript and creating constructors, and I came across this perplexing code.

var foo = function(){
   this.x = 1;
   return function(){
      return this.x;
   }
}
var x = new foo();
console.log(x);

I executed the following for this:

console.log(x); // The given output is expected for this line of code
console.log(x());
console.log(x()());
console.log(x()()());

All of the above gave me the same output as following:

function (){
   return this.x;
}

Can somebody explain what is happening in the above code. I could not give a proper title for this question. Sorry about that.

Note: I'm aware of constructors in JS. And the above code was just out of curiosity.

0

4 Answers 4

4

To make a long story short - it's not doing anything useful.

If a constructor returns an object, then the value produced by the new expression is that value rather than the constructed object. So instead of getting an instance of foo, you are getting a function that returns this.x.

It looks like this code is trying to produce a function that returns the this.x value of the created object, but that's not what it's doing. Since you are calling x() by itself, this.x is actually referring to the global x variable, so no matter how many times you call x()()(), it just returns itself.

If you used any variable name other than x and did not create an x variable (e.g. y), then y() would just return undefined, and y()() would produce a ReferenceError.

This would also fail much sooner in strict mode, becuase this inside the function would be referring to undefined when you tried to call it.

Sign up to request clarification or add additional context in comments.

1 Comment

Urghh... I should have put a little more thought into it. Still thanks.
0

My interpretation is this: x contains the result of calling foo().

foo() returns a function:

function(){
      return this.x;
}

the body of this function is written to the console

4 Comments

Then why calling x()()()()() will still return the function body?
@ArtyomNeustroev that fails with error Uncaught TypeError: undefined is not a function - jsfiddle.net/arunpjohny/pbm2k37y/2
@ArunPJohny does it throw error when executed inside DevTools console? Because it does not for me.
Well I hope you got the answer now as mentioned by @JLRishe . The first call gives x the return value (in this case the function). Then since the context is not returned, calling x() executes in Window context-> the return function executes this.x. "this" here is the window. Hence window.x is returned, which is the first returned function. y = 10; var foo = function(){ this.x = 1; return function(){ return this.y; } } var x = new foo(); console.log(x()); This gives value of window.y ==> 10
0

Here is an example to the previous answer, that demonstrates it:

var x = 5;
var foo = function(){
   this.x = 1;
   return function(){
      return this.x;
   }
}
var b = new foo();
b() //--> 5

Comments

0

This code is all about function invocation context.

At runtime, the this referenced in this.x = 1; is bound to a different object than the this referenced in return this.x;

x() invokes the anonymous function returned by foo, in a global context. For ECMAScript 3 (and earlier) environment, global context function invocation binds the global object to this, inside the invoked function. Thus, return this.x; refers to var x you define on the global object.

In ECMAScript 5, use strict; statement can be placed in any function declaration to disable the binding of the global object in "this" way.

The anonymous, nested function can access "foo's" this in a closure:

var foo = function(){
   this.x = 1;
   var that = this;
   return function(){
      return that.x;
   }
}
var x = new foo();
console.log(x); // function(){ ...
x(); // 1

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.