0

I am defining the consctructor function Foo as:

function Foo () {
    var a= 0;
    this.b = 1;
    this.f1= function () { return a; };
    this.f2= function () { return b; };
}

and I am creating the object as:

var bar= new Foo();

return b does not work, I have to use return this.b instead. But it work fine with the a variable. Why?

John L.
  • 1,825
  • 5
  • 18
  • 45
  • The keyword this doesn't mean what you think it does in this context sir. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this – Neo Dec 05 '16 at 17:40
  • Because there is no variable named `b` – Oriol Dec 05 '16 at 17:58

3 Answers3

0

Your function declares two types of constructs. var a is a normal variable that is scoped to the function and it is private within the function. It can be used any way the function needs to, so returning it is no problem at all. Most importantly, its value will not change from one instance of Foo to the next.

b, f1 and f2 aren't being declared as variables. They are being declared as "instance properties", meaning that their data will change from one instance of the object to another. If you want to return an instance property value, you must use this to return the value associated with that particular instance.

After all, if you wrote:

var obj1 = new Foo();
obj1.b = 10;

var obj2 = new Foo();
obj1.b = 20;

How would you be able to keep the two b values separate from each other? The answer is that you have two instances of a Foo object and the obj1 and obj2 variables each store a reference to their own instance.

When you write obj1.b, you need access to the b property that belongs to the obj1 object instance. The this keyword does this for you.

Read on for more details:

The this object binding is volatile in JavaScript...that is, it doesn't always point to the same object and its binding can change from one line of code to the very next. How you invoke the code that contains the word this determines what object it will bind to.

Here's a checklist that you can follow to know what this will bind to...

If the code that contains this is invoked:

  1. As a method or property of an object instance (through an instance variable):

    var o = new Object(); 
    
    // "this" will be bound to the "o" object instance
    // while "someProperty" and "someMethod" code executes
    o.someProperty = someValue;
    o.someMethod();
    
  2. Via a .call(), .apply(), .bind() or Array.prototype.fn invocation:

    // "this" will be bound to the object suppled as the "thisObjectBinding"
    someFunction.call(thisObjectBinding, arg, arg);
    someFunction.apply(thisObjectBinding, [arg, arg]);
    var newFunc = someFunction.bind(thisObjectBinding, arg, arg);
    

    Additionally, several Array.prototype methods allow for a thisObject to be passed which will alter the binding for the duration of the method call:

    Array.prototype.every( callbackfn [ , thisArg ] )
    Array.prototype.some( callbackfn [ , thisArg ] )
    Array.prototype.forEach( callbackfn [ , thisArg ] )
    Array.prototype.map( callbackfn [ , thisArg ] )
    Array.prototype.filter( callbackfn [ , thisArg ] )
    
  3. If none of the other scenarios apply, Default binding occurs.

    3a. With "use strict" in effect: this is undefined

    3b. Without "use strict" in effect: this binds to the Global object

** NOTE: this binding can also be affected by using eval(), but as a general best practice, the use of eval() should be avoided.

Scott Marcus
  • 64,069
  • 6
  • 49
  • 71
0

When your function

f1

is invoked, it asks it's environment/context "Excuse me, do you have any idea what [a] is please?". It responds with "Not here, but let me ask my own environment/context whether or not it knows what [a] is... ah hah, it says it knows what [a] is, and it's value is 0.".

When your function

f2 

is invoked, it asks it asks the same question of [b] as f1 did for [z]... the difference is, the environment/context it is looking in for [b] does not include the instance of Foo to which [b] has been attached.

'this' in JavaScript is a tricky subject, and is covered in great detail in this free online book which is part of the series "You don't know JS", by Kyle Simpson. A very good series.

BubbleHulk
  • 78
  • 8
0

It doesn't return because b is not declared.

function Foo () {
    var a = 0;
    this.b = 1;
    var b = this.b;
    this.f1= function () { return a; };
    this.f2= function () { return b; };
}

should work fine.

Or you can bind f2 method to "this" and return it:

function Foo () {
    var a= 0;
    this.b = 1;
    this.f1= function () { return a; };
    this.f2= (function () { return this.b; }).bind(this);
}
Leonid Lazaryev
  • 326
  • 1
  • 8