The provided resources contain a lot of useful info about JavaScript
closures and function/method functioning. I suggest to read them and
even bookmark them.
Still in more direct relation with difficulties which you are
experiencing is the distinction between CURRENT OBJECT and DEFAULT
OBJECT and their semi non-orthodoxy implementation in JavaScript.
The current object is always pointed by [this] keyword. Picturally (but
unofficially) it could be said that [this] points to whoever requested
at this time to execute the current chunk of code. In your sample
SomeObj is the one who requested useDoSomething execution and [this]
points to SomeObj.
The default object is the object where the engine searches first for
requested properties (against of what it tries to resolve the given
identifier): if no other object was explicitly indicated. Picturally
(but unofficially) if you say "go get me that" and if you did not
specify exactly where to get it, the default object will be the first
place the engine will search. More officially the default object is the
one placed at the top of the scope chain (where the bottom of this
chain is always points to the global scope). If the requested property
is not presented in the local scope, the engine goes further by the
scope chain and it looks at the global scope. If still no luck then the
engine gives up and it errors out.
Because instead of
window.alert('Hi!')
window.document.write('Hi!')
we can (and mostly do) use
alert('Hi!')
document.write('Hi!')
some language references state that [window] object *is* the default
object by default. That is an error. [window] object has nothing to do
with the default object; but because [window] and Global object are
made to act as one unit, the engine will find window fields and methods
at the end of the scope chain, just like it finds variable foo in
var foo = 'bar';
function f() {
alert(foo);
}
The resolution of 'alert' and 'foo' identifiers above goes by
equivalent schema: with searching 'alert' and 'foo' in the local scope,
failing - then finding them in the global scope. That is why in
time-crucial applications (say graphics intensive ones) it is a good
idea to use fully-qualified path to window methods: it saves the engine
from searching and failing first in the local scope. Depending on the
complexity of the local scope structure the productivity gain for
looped calls can be very noticeable.
In some languages current object and default object are made to act in
relay thus if an identifier cannot be resolved against default object
it will be tried against current object. Some languages have default
object accessor shortcut (dot - member name). JavaScript doesn't
implement the first and it doesn't have the second. In JavaScript
current object and default object are two totally separate programming
entities.
With this in mind you can now explain yourself now the engine behavior:
1)
useDoSomething : function()
{
return doSomething();
}
No object is indicated, so the engine first looking for doSomething in
the local function scope. It doesn't find it there so it looks for
doSomething in the global scope; still no luck == error.
That is an overall bad idea: but just to stress once again the
difference between current and default objects you could "fix" this
code by forcing both current and default objects to point to the same
object:
useDoSomething : function()
{
with (this) {
return doSomething();
}
}
2)
useDoSomething : function()
{
return this.doSomething();
}
The engine searches for doSomething in the current object which is set
to SomeObj in this case. Success!
3)
useDoSomething : function()
{
return SomeObj.doSomething();
}
The engine searches for doSomething in the explicitly indicated object
SomeObj. Success once again.
The behavioral difference between 2) and 3) is that current object is
not always the same object which you have initially assigned property
to. As I pointed out in another post, JavaScript doesn't have ideas of
"private property" and "exclusive ownership" as such
The fact that
you assign a reference to anonymous function to SomeObj.useDoSomething
property - this fact doesn't create any exclusive relations between
SomeObj, useDoSomething and the said anonymous function. Any amount of
other objects can get a reference to this function and respectively
current object ([this] value) will be set to these objects during the
function execution:
var SomeObj = {
doSomething : function()
{
return 'Did something';
},
useDoSomething : function()
{
return this.doSomething();
}
}
alert(SomeObj.useDoSomething());
var OtherObj = new Object();
OtherObj.doSomething = function() {return 'OtherObj';}
OtherObj.useDoSomething = SomeObj.useDoSomething;
alert(OtherObj.useDoSomething());
Practically it means:
1) If your object is a singleton (it is supposed to be only one
instance of this object in the whole execution context) you may want to
use the singleton name instead of [this] inside its methods. This way
if someone assigns a reference to a singleton method to another object
(just like above) the method behavior will be most probably
dissatisfactory for the "borrower".
2) In any other case [this] is preferable and often the only one usable
alternative.