Javascript confusion....

  • Thread starter George Ter-Saakov
  • Start date
G

George Ter-Saakov

I am trying to get into depth of JavaScript a little more and find it a bit
confusing for person who is used to C#/C++ object oriented approach..

So I need some help in understanding how staff works... Given following
object definition

ZColor = function(num)
{
var a = num + 1;
this.b = num + 2;
this.show = function()
{
alert(a);
alert(this.b);
}
}



I have folowing code that runs when htm page is loaded.

var obj = new ZColor(6);
setInterval(obj.show, 1000);

So it produces 2 alerts. First is "7" and second is "undefined"
So basically show method has access to "a" variable and does not have access
to "b" variable...

I do understand why "alert(this.b)" does not work from timer function. Cause
timer has not idea that i want to run it under "obj" as "this" scope.

But what puzles me is why "alert(a)" works... .

Thanks
George.
 
B

bruce barker

its called closure. lisp (which the javascript vm is a close parallel to),
was one of the first languages to support it. but most modern languages do
now, phython, ruby, even c# (since v2). closure is generally used to pass
variables to a delegate definations, and has its own scoping rules.

javascript is pure object language (though does not implement inheritence,
though many javascript frameworks like ms ajax implement it).

a function declaration in javascript can be though of as an object
constructor function, though javascript allows object constructors to return
a value (unlike c#). unlike c#, all function calls in javascript are instance
methods calls. in the following:

function a() {alert('a called');}
a();

you might think that a() is static call like in c#. but its not, when
javascript calls a(), an object instance is created via the object
construcotr a, then the object is released.

javasction functions can also be used as delegates (again they are objects
just like delagates in c#). again when a function used as delegate its used
as the constructor of the delegate:

setInterval(obj.show, 1000);

you are passing obj.show as a delegate, so when show is called, it
constructs a new object, for which b is undefined. but the "a" variable in
"show" referes to the "a" variable in its parent containing function, so it
is a reference to it.

you can do the same thing in c#

public delegate string myDelegate();
void createDelegate(string a)
{
callDelegate( new delegate() { Console.Write(a); });
}
void callDelegate(myDelegate func) { func(); }


-- bruce (sqlwork.com)
 
A

Anthony Jones

George Ter-Saakov said:
I am trying to get into depth of JavaScript a little more and find it a bit
confusing for person who is used to C#/C++ object oriented approach..

So I need some help in understanding how staff works... Given following
object definition

ZColor = function(num)
{
var a = num + 1;
this.b = num + 2;
this.show = function()
{
alert(a);
alert(this.b);
}
}



I have folowing code that runs when htm page is loaded.

var obj = new ZColor(6);
setInterval(obj.show, 1000);

So it produces 2 alerts. First is "7" and second is "undefined"
So basically show method has access to "a" variable and does not have access
to "b" variable...

I do understand why "alert(this.b)" does not work from timer function. Cause
timer has not idea that i want to run it under "obj" as "this" scope.

But what puzles me is why "alert(a)" works... .

Take a look at this:-

var x = 0

function fnA()
{
var a = 1

function fnB()
{
var b = 2

function fnC()
{
var c = 2

alert(c); alert(b); alert(a); alert(x)
}

fnC()
}

fnB()
}

fnA()

You get alerts 3, 2, 1, 0.

All javascript code runs in what is known as an "Execution Context". The
outer context being known as the global scope. In the above case the
identifiers x and fnA is add to the global scope.

When a function is created (note not when its executed) it has added to it a
scope object (in IE this isn't accessible from code) which is a reference to
the context in which it is created. Hence in the case of fnA the global
context is added as its scope object. (Note functions are objects
themselves which can have members. Very loosely you could think of them as
static members).

When a function is called a new "Execution Context" is created. Hence when
fnA() is called a new context is create to which the identifiers b and fnB
are added. As fnB is created the fnA() execution context is added as its
scope object.

When fnB() is executed yet another context is created to which the
identifiers b and fnC are added. As fnC is created the fnB() execution
context is added as its scope object.

When we get to the execution of alert(c) in fnC() javascript needs to find
the identifier c. It starts with the current execution context which has an
identifier c so returns its value.

On alert(b) the identifier b needs to be found. Javascript can't find it in
the current execution context so it attempts to find it in another execution
context. It finds this execution context by looking at the function object
whose code it is executing. It then retrieves the execution context
attached to it as the scope ojbect. In this case that will be the
outstanding execution of fnB which does have b identifier so that value is
returned.

On alert(a) the identifier a isn't found in the current context. An attempt
to find it in the the fnC.scope object (fnB() execution context) also fails.
Since the scope object is also an execution context (of fnB) it in turn can
fetch the scope object attached to fnB, the execution context of fnA. An
attempt is made to find a in that context and succeeds. This is known as
walking the scope chain. (Google: Javascript scope chain).

On alert(x) the scope chain is walked all the way up to the global scope to
find the identifier x.


So lets take a look at your original code:-


ZColor = function(num)
{
var a = num + 1;
this.b = num + 2;
this.show = function()
{
alert(a);
alert(this.b);
}
}

var obj = new ZColor(6);
setInterval(obj.show, 1000);

The new ZColor(6) does two things. new creates a new instance of an object
and creates an execution context. NB. The created object and the execution
context are _NOT_ the same object.

var a = num + 1;

The identifiers num and a are added to the execution context and a is
assigned a value.

this.b = num + 2

The object created by the new keyword will be the 'this' object and this
object that gets the identifier b.

this.show = function() { ... }

Here function() { ... } creates a new function whose scope object is
assigned as the current context (the one contain num an a). This function
is now assigned to the 'this' object with the identifier show. This is
significant. You have created a closure (Google:Closure Javascript) where a
function create inside an execution context has escaped from it and is
reference from the outside. (C# has a similar concept in the that anonymous
functions can capture variables in scope with them. A big difference is
that C# only captures variables that the delegate uses where as a Javascript
closure will capture all variables in the scope chain).

var obj = new ZColor(6)

Exection context for ZColor(6) will still exist and will not be GC'd. :-

obj -> show -> (scope (ZColor(6) execution context)) -> a

setInterval(obj.show, 1000)

Cause the show function to execute with the global object (window) as its
'this' object.

alert(a)

The identifier a is not found in the context of the current show()
execution. Javascript looks at the scope object of show and finds it there.

In effect we are using the Execution context of ZColor(6) as a place where
private members and functions can exist.

alert(this.b)

window doesn't have a b property nor has a b property been var'd in global
scope.

Hope this doesn't confuse too much those googles should help

Since you investigating Javascript OO you should also be aware of another
chain in javascript known as the prototype chain:-

function MyBase(x) {this.x = x}
MyBase.prototype.myFunc1 = function() { this.x += 1}
MyBase.prototype.myFunc2 = function() { this.x += 2}

function MyDerived(x) {this.x = x}
MyDerived.prototype = new MyBase()
MyDerived.prototype.myFunc2 = function() {this.x -= 2} //override
MyDerived.prototype.myFunc3 = function() {this.x += 3}

Note that since all functions are created in the global scope they have no
access anything that can hold values private to an instance. Hence private
members need be added as public attributes on the object with perhaps some
naming convention which would make it obvious when code is using them
inappropriately.
 
G

George Ter-Saakov

Thanks, I think i am getting closer to understanding it.
Need to use it in real life...

George
 
G

George Ter-Saakov

Thanks, I did not have exposure to any of those languages "ruby, python,.."
So that thing is quite new for me.

The parallel you made between closure and delegates does help although it
seems to me the "closure" is much "bigger" in terms of functionality.
On the other hand I do not see much use of it (right now) except imitating
delegates :)


George
 
A

Anthony Jones

George Ter-Saakov said:
Thanks, I did not have exposure to any of those languages "ruby, python,.."
So that thing is quite new for me.

The parallel you made between closure and delegates does help although it
seems to me the "closure" is much "bigger" in terms of functionality.
On the other hand I do not see much use of it (right now) except imitating
delegates :)


One use is to solve the 'this' problem you identified:-

ZColor = function(num)
{
var a = num + 1;
this.b = num + 2;
this.show = function()
{
alert(a);
alert(this.b);
}
}

function setInterval3(fn, period, target)
{
setInterval(function() {fn.call(target)}, period)
}

var obj = new ZColor(6);
setInterval3(obj.show, 1000, obj);

In this case the alert(this.b) will now work
 

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,763
Messages
2,569,562
Members
45,038
Latest member
OrderProperKetocapsules

Latest Threads

Top