PDA

View Full Version : Javascript Variable Scope



PuritysDisciple
21 Feb 2007, 7:00 AM
This may be a newbie question, but I can't seem to figure out how to do this.

I am trying to setup an object hierarchy so that child objects have access to the parent object's "global" variables, but all I can seem to get is undefined.



var FOO = {};
FOO.Bar = function(){
var subchild;

return {
init: function(){
subchild = new FOO.Cat(1);
}
};
}();

FOO.Cat = function(id){
this.init(id);
};

FOO.Cat.prototype = {
init: function(id){
this.id = id;

if(this.id === subchild.id)
{
alert("Hi!");
}
}
};

FOO.Bar.init();


from what I understand about javascript scope subchild should have access to the subchild variable from within itself. For some reason though, I get undefined.

Any thoughts?

brian.moeskau
21 Feb 2007, 7:37 AM
It doesn't look like you are actually inheriting anything from anything else. Just because Bar creates a private instance of Cat, that doesn't create any type of relationship between the two classes. Cat knows nothing about Bar, so of course can't access it's private members. For a general overview of how you might do this generically in javascript, see something like:

http://www.cs.rit.edu/~atk/JavaScript/manuals/jsobj/

In Ext however, there is functionality built-in that makes inheritance even easier. Check out the documentation for the extend() method:

.33 version (YAHOO.extend):
http://www.yui-ext.com/deploy/yui-ext/docs/output/YAHOO.html#extend

In 1.0, it has moved to Ext.extend, but it's the same thing.

brian.moeskau
21 Feb 2007, 7:42 AM
I guess I should add that the docs for extend() may not make much sense if you aren't fully clear on its purpose or what it actually does, so the best way to learn is to jump into the source code and see the existing patterns for how this is done. Basically, if you just look in ext-all.js and search for ".extend" you'll see many examples of this pattern and should be able to get the hang of how to do it.

PuritysDisciple
21 Feb 2007, 7:46 AM
Im not looking to extend FOO.Bar I am looking for a way to have the instance of FOO.Cat be able to have access to the "global private" variables of its parent object FOO.Bar. I cant for the life of me find a way to do this.

Let me see if I can clearify this more:
Im looking to use FOO.Bar as an application with a section of the application (FOO.Cat) having access to the overall application when it needs to.

This just came to me while I was writing:


var FOO = {};
FOO.Bar = function(){
var subchild;

return {
init: function(){
subchild = new FOO.Cat(1,this);
},
getSubChild: function(){
return(subchild);
}
};
}();

FOO.Cat = function(id,parent){
this.init(id,parent);
};

FOO.Cat.prototype = {
init: function(id,parent){
this.id = id;
this.parent = parent

if(this.id === this.parent.getSubChild().id)
{
alert("Hi!");
}
}
};

FOO.Bar.init();


this seems to work, but also seems to be a dirty-hacked-up way to do it. If anyone knows of a cleaner way to do this, please let me know.

PuritysDisciple
21 Feb 2007, 9:06 AM
This is the best way I can think of to explain what I am trying to do without posting my entire application (which is an internal application, so I cant post it).



var COMPANY = {};
COMPANY.App = function(){
var appsetting = true;
var module1;
var module2;

return {
init: function(){
module1 = new COMPANY.App.Module1();
module2 = new COMPANY.App.Module2();

module2.doSomethingElse();
module1.doSomething();
}
};
}();

COMPANY.App.Module1 = function(){
this.init();
};

COMPANY.App.Module1.prototype = {
init: function(){
this.working = true;
},
doSomething: function(){
if(appsetting)
{
alert("Appsetting Is True!");
this.working = false;
}
}
};

COMPANY.App.Module2 = function(){
this.init();
};

COMPANY.App.Module2.prototype = {
init: function(){

},
doSomethingElse: function(){
if(module1.working)
{
alert("unable to do something else, module 1 is working!");
}
}
};

COMPANY.App.init();


the result of this application should be 2 alerts:

unable to do something else, module 1 is working!
Appsetting Is True!

However I can't find an efficient way to do this. If there is another way to achieve this, please let me know.

brian.moeskau
21 Feb 2007, 1:48 PM
Well, I have to admit, I still don't fully understand what you are trying to do -- you obviously have some constraint regarding how you can set things up, but it's not clear why. I am certain that there's a better pattern though.

- Aggregation: rather than a parent class creating two "sub" classes that have to talk to each other, can one of the subclasses create an instance of the other so it's a single chain and the creator would have access to calling methods on the child? It seems like only Module2 has to know about Module1, but perhaps that's just because your example is simplified.

- Observable: this is probably the best pattern for this type of thing I would think. If you have classes that need to be able to communicate things like state changes to other objects arbitrarily, outside of any direct class relationship, you could inherit those classes from Observable and have them fire events. The classes could subscribe to each others' events and set flags in response to those events, rather than trying to call up through a chain of objects each time to check properties.

Looking at your example, while you could possibly get it to work, you are right to suspect that it feels like a hack. I would personally try to attack the problem using an established pattern if possible so that it's clear to all what the code is doing.

brian.moeskau
21 Feb 2007, 1:53 PM
Another good pattern for this, since the timing of your objects' creation seems to also be important (so one may not exist when the other raises an event), is to create a separate Manager class that maintains state, and each business object simply registers state changes and checks for state with the Manager before doing something. That way the individual classes only have to know about the Manager, not about every other possible business object.

PuritysDisciple
21 Feb 2007, 2:16 PM
A manager class seems like a great way to work things. I had not thought about that one (im still pretty new to OOP in javascript). Ill deffenitly try and implement a manager class as well as observable. Thanks!