Another Object literal Question!

E

emailscotta

Below I declared a basic object literal with 2 methods. The
"doSomething" method is call from the "useDoSomething" method but the
call is only sucessful if I use the "this" keyword or qualify the call
with "SomeObj".

Can someone describe why this is happening?

var SomeObj = {
doSomething : function()
{
return 'Did something';
},

useDoSomething : function()
{
//Doesn't work - doSomething() no defined.
return doSomething();
//Works
//return this.doSomething();
//Works
//return SomeObj.doSomething();
}
}

alert(SomeObj.doSomething());
alert(SomeObj.useDoSomething());
 
R

RobG

Below I declared a basic object literal with 2 methods. The
"doSomething" method is call from the "useDoSomething" method but the
call is only sucessful if I use the "this" keyword or qualify the call
with "SomeObj".

Can someone describe why this is happening?

var SomeObj = {
doSomething : function()
{
return 'Did something';
},

useDoSomething : function()
{
//Doesn't work - doSomething() no defined.
return doSomething();
//Works
//return this.doSomething();
//Works
//return SomeObj.doSomething();
}
}

alert(SomeObj.doSomething());
alert(SomeObj.useDoSomething());

This thread may help:

<URL:
http://groups.google.com/group/comp...le+scope+and+closures&rnum=1#d2a7ee1707cd0a9a
 
E

emailscotta

I'm still a little confused because I don't see where any closures are
formed.

I am unsure of why an one method of an object literal does not have
access to another method of the same object literal.

I'm probably not explain myself very well, sorry!

RobG wrote:
[...]
This thread may help:

Actually a better reference is Richard's closures article, it is very
comprehensive. It covers much more than just closures:

<URL: http://www.jibbering.com/faq/faq_notes/closures.html >
 
M

Michael Winter

I'm still a little confused because I don't see where any closures
are formed.

There aren't any in the code you posted.
I am unsure of why an one method of an object literal does not have
access to another method of the same object literal.

The properties of an object literal do not affect the scope chain. The
property is only added to the newly-created object itself, and will only
be visible if accessed through that object using the this operator or
some other reference.

Though the closures article in the FAQ notes isn't directly relevant, it
does discuss how the scope chain is constructed and how properties are
added to the objects in that chain. Only the means described therein -
formal arguments, function declarations, and variable declarations -
perform the latter.

[snip]

Mike


Please do not top-post when replying to this group.
 
R

RobG

I'm still a little confused because I don't see where any closures are
formed.

Please don't top post, reply below trimmed quotes.

The function statements themselves don't create any closures. The
article I referred to has some good information on how functions are
instantiated, I didn't mean to set you on down the wrong path.

I am unsure of why an one method of an object literal does not have
access to another method of the same object literal.

The scope of function objects is based on their prototype chain and is
defined when you declare the function, though you can change it by
subsequently modifying the prototype chain. In your object literal,
you don't place SomeObj on the function's scope chain, therefore its
properties are not available to the function.

The this keyword is given a value *when the function is called* that is
a reference to the object that the function is being called as a method
of. In your original post you had:

var SomeObj = {
doSomething : function() {
return 'Did something';
}
},
useDoSomething : function() {
return this.doSomething();
}
}
alert(SomeObj.doSomething());
alert(SomeObj.useDoSomething());

If you do:

var anotherObj = {};
anotherObj.useDoSomething = SomeObj.useDoSomething;
anotherObj.useDoSomething();

you'll get an error, because when called as a method of anotherObj,
useDoSomething's this keyword will point to anotherObj, which doesn't
have a doSomething method.


It covers quite a bit on what happens when function objects are created
and called.
 
V

VK

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.
 
R

Richard Cornford

VK said:
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.

I suggest that as some point _you_ try reading and _understanding_ them,
as bookmaking then is hardly a useful substitute.

.... 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

"Requested property" is potentially confusing and misleading. The _only_
constructs in javascript that are resolved against the scope chain are
Identifiers, while 'requesting' a 'property' would be implied in property
accessor resolution.
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.

Are you saying that some references state that the window object is the
first object on the scope chin by default (whatever "by default" is
supposed to mean in this context)? You can cite these "references"?

Of course if you insist on using "default object" as a label for the
object at the top of the scope chain then the window/global object is the
"default object" in the global execution context. And as the global
execution context is the execution context that code always first enters,
and so may be regarded as the "default" (entering any other execution
context requires explicit scripted instructions), it would be true to say
that window/global object is at the top of the scope chain' by default'.
[window] object has nothing to do
with the default object;

Apart from being the object at the top of the scope chain (your "default
object") in the ('default') global exect5uion context.
but because [window] and Global object are
made to act as one unit,

There is no practical sense in which they are not the same object.
the engine will find window fields and
methods at the end of the scope chain, just like it
finds variable

Which is what would be expected if they are the same object.
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.


The whole mechanism of closures relies on the fact that there may be more
than two objects on the scope chain. What you are referring to as "the
local scope" is the Activation/Variable at the top of the scope chain
(the thing that would be your "default object" by default). there may be
numerous other Activation/Variable objects on the scope chain (along with
any objects added deliberately added to the scope chain of functions
using the - with - statements).

The indefinite length of the scope chain, and the fact that Identifier
resolution works down the chain kink by link, is one of the reasons that
it is referred to as a 'chain'. If it was as simple as just a local
object and a global object then the two could be described as 'the local
scope' and the 'global scope', but the real mechanism is more complex
than that.
That is why in time-crucial applications (say graphics
intensive ones) it is a good idea to use fully-qualified
path to window methods:

You are about to put your foot in your mouth agian.
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.

Pure bullshit! What you are referring to as a "fully-qualified path to
window methods" is using the property accessor - window.alert - in place
of the Identifier - alert -, for example. What you are failing to take
into account is that the - window - in - window.allert - is an
Identifier, and so will be resolved against the scope chain.

To resolve the Identifier - alert - the engine will examine the object at
the top of the scope chain to see if it (or an object on its prototype
chain, if any) has a property named "alert". If we assume that that
object has no "alert" property then the engine moves on to the next
object on the scope chain and does the same test. The global object is
the last object on any scope chain, so if we assume that no object higher
up the chain had an "alert" property than the resolution of the
Identifier ends when the "alert" property of the global object is found.

If the property accessor - window.alert - is resolved the fist step will
be resolving the Identifier - window -, which uses the same mechanism as
the resolution of the Identifier - alert -. If we assume that no other
object on the scope chain has a property named "window" then the process
ends when the "window" property of the global object is found. So the
resolution of the Identifier - window - will take almost exactly the same
amount to time as the resolution of the Identifier - alert - (if we are
using the same scope chain as with - alert -). However, resolving the
property accessor - window.alert - is not over yet, as now the object
referred to by value of the "window" property of the global object needs
to be examined to see if it has a property named "alert".

The logic of the mechanism says that property accessors referring to
properties of the global object will take longer to resolve than
Identifiers referring to properties of the global object. And you may
recall that the list time you were corrected on this point you were shown
code that demonstrated an empirical test where the results showed
Identifier resolution to be faster property accessor resolution, even on
Windows IE, where there is most reason to expect the outcome to the
other.

Th notion that "fully-qualified paths" are quicker is an old wives tail,
that if it was ever true certainly is false with current browsers.
In some languages current object ...
<snip - waffle>
.... only one usable alternative.

So may words, so little understanding.

Richard.
 
M

Michael Winter

VK wrote:

[snip]
Still in more direct relation with difficulties which you are
experiencing is the distinction between CURRENT OBJECT and DEFAULT
OBJECT

Can't you just use phrases similar to "the this operator value", "the
object referred to by the this operator", or "scope chain"? They might
be more verbose, but at least they mean something unambiguous.
and their semi non-orthodoxy implementation in JavaScript.
Huh?

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.

A succinct (and accurate) description would be:

The this operator refers to the penultimate member of a member
expression, or, if there is no such member, to the global
object. This behaviour can be overridden using the
Function.prototype.apply and call methods, which specify the
object directly.

That is, in the expression,

a.b.c()

'b' is the penultimate member and the this operator will refer to that
object. In the expression:

f()

there is no member expression at all, so the this operator will refer to
the global object. Finally, with:

f.call(o)

the first argument to the call method specifies the object to use. If
null or undefined, the this operator refers to the global object.
Otherwise, it refers to the first argument (though see below).

One should also note that the this operator always refers to an object.
Given the object,

var object = { property: 'value' };

and the expression:

object.property.charAt(0)

one immediate observation is that property is not an object; it is a
string value. In cases such as this, the value is temporarily converted
to an object (a String object here because it's a String value), and
evaluation of the rest of the expression continues from there.

Similarly, if the first argument to the Function.prototype.apply or call
methods is a value, that value is converted to an object.

<aside>
This is why values cannot take on properties: the object used in that
process is only temporary and when the object is no longer needed, it
and its properties cease to exist.
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.

This is part of the reason why "default object" is dubious: there is no
single object used for identifier resolution. The scope chain consists
of numerous objects, each of which is examined in turn until the
relevant property is located, or the end of the chain is reached.

[snip]
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.

Rubbish. If an identifier is used as the left-most member in a member
expression, then the scope chain still needs to be searched to determine
what value or object reference that identifier represents. Including a
reference to the global object unnecessarily should actually result in a
marginal decrease in performance as, once it's found, the property that
follows must then be located - an extra step.

[snip]
useDoSomething : function()
{
with (this) {
return doSomething();
}
}

That would be an utterly stupid thing to do.

[snip]
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.

Why? Surely it's more reasonable to require that client code behaves itself.

[snip]

Mike
 
V

VK

I suggest that as some point _you_ try reading and _understanding_ them,
as bookmaking then is hardly a useful substitute.

For what purpose? I already accepted the fact that in the whole world
there are only 4-6 extremely carefully selected people able (by their
outstanding mental capabilities) to understand JavaScript - or at least
to come close to its understanding.
The very nature of JavaScript - which is one of the most sophisticated
creations of the human mind - eliminate any possibility to talk about
it by using vernacular constructions. Therefore and hereafter a strong
understanding is required in a special language particularly developed
to express entities and processes in JavaScript language. Despite this
special metaphysical language is primarily based on British English, a
proper knowledge of its grammar and especially a proper knowledge of
entities pointed by lexems of the said language require years of
careful studies under strict supervision of the above mentioned people
- if they decide that the mental capabilities of the challenger will
ever let him/her to achieve any success in the future. Even after
become fluent in that special language, the person is still nowhere to
understand JavaScript. She's only making an important yet preliminary
step towards the achievement. Namely she's getting ready to read the
texts of the Books of ECMA - under the same strict supervision in order
to ensure the proper understanding of all passages. If this second
stage is passed successfully and the challenger escaped the regular
risks to die of the boredom or a brains overheat - then she's finally
conditionally acknowledged as able to understand JavaScript. The
drawback is that on this stage a proper description of any JavaScript
phenomenon by former challenger requires the use of the metaphysical
language she learned before: that makes her speech (though crystal
clear for anyone from the selected ones) hardly understandable for
regular people.

This way I'm not pretending to ever understand JavaScript and I'm
afraid I'll never have a time to learn the language to talk about
JavaScript.
Sometimes (but very often) I'm just trying to answer a question if I
see that more explanations expressed in that language OP gets - more
confused it becomes.

:)
 
J

John G Harris

Despite this
special metaphysical language is primarily based on British English,

So you can't understand "customise" because it doesn't end in -ize. Boy,
have you got problems.


This way I'm not pretending to ever understand JavaScript and I'm
afraid I'll never have a time to learn the language to talk about
JavaScript.
<snip>

We had noticed.

John
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,996
Messages
2,570,237
Members
46,825
Latest member
VernonQuy6

Latest Threads

Top