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:
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();
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 ] )
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.