Scope Chains and Method Invocation.

E

emailscotta

After reading Richard's article,
http://www.jibbering.com/faq/faq_notes/closures.html, I would like to
re-visit an earlier post of mine. I think I know understand why the
code doesn't work but would like to get some verification. Below is
some code and below that is an explanation of what I think is
happening.

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

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

}

document.writeln(obj.doSomething());
document.writeln(obj.useDoSomething());


1) Global Variable Instantiation
- A named property of the global object is created, SomeObj.
- But the object is not created until the assignment statement
is executed.

2) Code execution begins
- assignment statement var SomeObj = {....} is executed.
- an execution context is created.
- SomeObj is created with a [[scope]] contain only the
global object.
- Variable instantiation creates 2 named properties
doSomething and useDoSomething.

(Here where I think I'm going wrong)

- doSomething is created with a [[scope]]
containing SomeObj --> global object.
- useDoSomething is created with a [[scope]]
containing SomeObj --> global object.


Since the code does not work SomeObj can not be on the scope chain and
scope chain for doSomething and useDoSomething must only contain the
global object.


I would also like to ask VK to refrain from replying to this message.
It seems that when Richard and VK get together an argument breaks out
and the question get lost. Sorry if this offend either of you I just
want to get my question answer.

Thanks for any help!
 
M

Matt Kruse

var SomeObj = {
doSomething : function(){return 'Did something';},
useDoSomething : function(){
//Doesn't work - doSomething() not defined.
return doSomething();
//Works
//return this.doSomething();
//Works
//return SomeObj.doSomething();
}
}
2) Code execution begins
- assignment statement var SomeObj = {....} is executed.
- an execution context is created.

A function hasn't been entered, so no execution context needs to be created.
Object creation does not create an execution context.
(Here where I think I'm going wrong)
- doSomething is created with a [[scope]]
containing SomeObj --> global object.

SomeObj is not in the scope chain, since it's just an object.

Now back to your original attempts:
//Doesn't work - doSomething() not defined.
return doSomething();

Since doSomething is a property of the same object where useDoSomething
exists, it won't be found. The object is not part of the scope chain.
//Works
//return this.doSomething();

Since 'this' refers to the object, this resolves specifically to the right
place and specifies the attribute to resolve.
//Works
//return SomeObj.doSomething();

Same here, but instead of resolving with 'this' you're resolving using the
attribute in the global namespace.

This may be more of what you're looking for:

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

This creates and runs a function, which creates a new execution context. The
doSomething function inside is only visible to things defined within the
execution context, so doSomething is in effect a private method.

Then an object is returned, which will be assigned to the SomeObj attribute
of the global object. In its scope chain is the anonymous function which
contains the doSomething function. So when doSomething() is fired from
within the useDoSomething function, it finds doSomething in its scope chain.
Since this object is returned, containing the anonymous function execution
context, and the outer anonymous function is executed, this creates the
closure. Since the execution context of the anonymous outer function is
still in the scope chain of the useDoSomething function, it has to continue
to exist, and take doSomething along for the ride.

I hope I was fairly clear. Richard may explain better, since a fair amount
of what I know on the topic I actually learned from him ;)
 
M

Michael Winter

[Apologies if this is double-posted]

(e-mail address removed) wrote:

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

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

}

document.writeln(obj.doSomething());
document.writeln(obj.useDoSomething());


1) Global Variable Instantiation
- A named property of the global object is created, SomeObj.
- But the object is not created until the assignment statement
is executed.

Yes. Variable declarations are processed before execution begins upon
entering an execution context. This results in the creation of
properties on the relevant variable object. However, any initialisers
are delayed until they are evaluated.

When evaluating "global" code, the variable object is the global object
itself.
2) Code execution begins
- assignment statement var SomeObj = {....} is executed.
- an execution context is created.

No. There is a running execution context - the one created when
executing global code - but that is the only execution context that
currently exists.

Object literals do not create execution contexts. Further execution
contexts are entered only by calling functions or constructors.
- SomeObj is created with a [[scope]] contain only the
global object.
- Variable instantiation creates 2 named properties
doSomething and useDoSomething.

Neither of those are correct, for the reason given above: evaluating an
object literal does not result in entering a new execution context.

An object literal creates a new object, as if by

new Object()

The comma-separated list of property names and values is then added to
that new object. The evaluation of

var object = { property : 'value' };

is equivalent to:

var object = new Object();

object.property = 'value';

Even if that string literal was replaced with a function expression,
there is nothing here that would cause its [[Scope]] property to contain
more than just the global object.
(Here where I think I'm going wrong)

- doSomething is created with a [[scope]]
containing SomeObj --> global object.
- useDoSomething is created with a [[scope]]
containing SomeObj --> global object.

Yes, that is wrong,
Since the code does not work SomeObj can not be on the scope chain and
scope chain for doSomething and useDoSomething must only contain the
global object.

.... and your reasoning is spot on.

[snip]
Thanks for any help!

I hope that helps,
Mike
 
R

Richard Cornford

After reading Richard's article,
http://www.jibbering.com/faq/faq_notes/closures.html, I would
like to re-visit an earlier post of mine. I think I know
understand why the code doesn't work but would like to get
some verification. Below is some code and below that is an
explanation of what I think is happening.

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

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

Although this will work it is not the way to do it as you should avoid
linking the Identifier - SomeObj - to the code within the value assigned
to that Identifier. When a method of an object is being called/employed
as a method of that object the code it contains should refer to the
object instance using the - this - keyword. That makes for more easily
portable and maintainable code as then the same structure can be employed
elsewhere or the Identifier changed, without having to go looking for all
the references to it in the contained code.
}

}

document.writeln(obj.doSomething());
document.writeln(obj.useDoSomething());


1) Global Variable Instantiation
- A named property of the global object is created, SomeObj.

And as it is a declared variable the property is gi9ven the -
DontDelete - attribute (so it cannot be deleted from the global object).
The value of the property is also provisionally given the Undefined value
as all existing properties must have a value.
- But the object is not created until the assignment
statement is executed.
Correct.

2) Code execution begins
- assignment statement var SomeObj = {....} is executed.
- an execution context is created.

An execution context (the global execution context) is created prior to
variable instantiation, which itself precedes the execution of any code
within the execution context, and so must happen prior to the assignment
operation being executed. No new execution context is created for the
evaluation of an object literal/intialiser.
- SomeObj is created with a [[scope]] contain only the
global object.

SomeObj - is just an normal object and normal object don't have [[Scope]]
properties. The two function objects created by the evaluation of the
FunctionExpressions within the object literal/initialiser do have
[[Scope]] properties, and those [[Scope]] properties both refer to a
scope chain that only includes the global object.
- Variable instantiation creates 2 named properties
doSomething and useDoSomething.

There is no variable instantiation in the evaluation of an object
literal/initialiser. The evaluation of such a construct involves the
creation of an object equivalent to a call to - new Object(); - and the
creation of properties of that object who's names correspond with the
Identifiers/string literals or numeric literals to the left of the colons
in the object literal and with the values assigned to those properties
having the value resulting from the evaluation of the Expressions to the
right of the colons.

This is, in this case an object is created equivalent to a call to - new
Object(); - and that object is given a property named "doSomething", the
FunctionExpression of - function(){return 'Did something';} - is
evaluated, resulting in the creation of a new Function object, and the
value of that Function object (a reference to the function object) is
assigned to the - doSomething - property of the object. And then much the
same happens for the "useDoSomething" property.
(Here where I think I'm going wrong)

- doSomething is created with a [[scope]]
containing SomeObj --> global object.

It is not. At no point does the object eventually referred to by the -
SomeObj - property of the global object find itself on the scope chain.
The [[Scope]] property of the Function object refers to a scope chain
that only contains the global object, because that is the scope chain of
the (global) execution context in which the Function object was created.
- useDoSomething is created with a [[scope]]
containing SomeObj --> global object.
Ditto.

Since the code does not work SomeObj can not be on the
scope chain and scope chain for doSomething and
useDoSomething must only contain the global object.

Yes, - SomeObj - is not on the scope chain of those function's execution
contexts when you run them.

Keep in mind that the scope chains that belong to execution contexts are
used to resolve Identifiers in code executed within those contexts, as
the source of the [[Scope]] properties of Function objects created within
those execution contexts and for nothing else. And that only Function
objects have [[Scope]] properties as [[Scope]] properties are only used
to define the scope chains used for their execution contexts when the
functions are executed. That is the extent of the role of scope chains
and [[Scope]] properties in javascript.
I would also like to ask VK to refrain from replying to
this message.
It seems that when Richard and VK get together an argument
breaks out and the question get lost. Sorry if this offend
either of you I just want to get my question answer.

Why should I be offended that you reject VK's nonsense. Indeed if more
people told VK what they thought of his 'contributions' he might find it
harder to dismiss the correction of his technical ignorance as the
product of prejudice, and actually see the need to learn something about
javascript before pontificating on the subject.

Richard.
 

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,764
Messages
2,569,565
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top