Make your own free website on Tripod.com

Scope of variables in the function and var


In the movieClip MC, we write the script as below

subMc.myObjT.methodU=function(paramV){
    var W=paramV+3;
    X=W+3;
    this.Y=X+3;
}

What are those variables belong to. Whose x, whose W, whose X and whose Y ?

Explanation:

This is to define a method of "MC.subMc.myObjT";
The object is myObjT and the method name is "methodU"

paramV represent what we supply in the parenthesis.

W is defined as var. It is create here and vanished at the end of this function.

These two variables have similar scope. They are within the function. It wont "conflict" with any variable name outside this function. Even we have a variables paramV or W in the MC, it will not affects them. The only limitation is that, we should avoid naming conflict with Flash keyword and the name of buld-in Object.

X is troublesome. Nothing is specified about the scope of it, so it has the scope "here" . Since that function is defined in MC, so it try to find X in MC. If not found, it try to find it in _global. Anyway, even this function is called by another movieclip, that X is almost always treated as MC.X, (the X in the timeline of present movieClip). If another movieClip or object borrow this function as its method, the X is still read from "here" - the MC.

This is not true for Flash 5. In Flash 5, unsepcified scope is treated as scope of "this". X is treated as this.X; See below. The result of this function is different in Flash MX and Flash 5 due to X;

this.Y is simple. It is belong to "this". However, what is "this" ? That function is a method of myObjT. So, myObjT will call this method and "this" means myObjT. A function can be assigned to be a method of another object. Thus, "this" will be another object. We have specified the scope, so it will not search in the _global scope if not found in this.

Here is a test. Can you see what is "this" ?

Movieclip.prototype.createSub(){
    this.createEmptyMovieClip("dummy",1);
    var pk=function(){
        trace(this.name);
        this.removeMovieClip();
        }
    dummy.onEnterFrame=pk;
}


Now, which movieClip will be removed ? the MovieClip itself or the submovieclip dummy ?


Further discussion about "var"

We believe a variable declared as "var" will be temporary variable that appears during that function call and diappears after the function ends. In fact, this is not necessary. The keyword "var" is mainly to define the "scope" of that variable. Whether it will die after the function ends is not the main concern. Here are some discussions about the keyword "var";


1.
var in timeline


It does nothing. Variable declared as "var" is treated the same as without "var". It lives there no die. Declare the same name of variable as var will not "reinitiate" anything. I was confused about this. We write scripts in frame block as if we are writing functions. We even use "return" to abort the script in frame script, so why the "var" thing behaves different ?

example of frame script: 

a=3;
var a;
// nothing happens, a is still 3
var a=4;
// this will set a to 4. 
trace(this.a);

When we say "var a=4;", the a is still "this.a", not a variable created in the function-process. It lives in the timeline and always accessible.


2.
var in function


A variable in the timeline may appear in the body of the function. It is treated as the variable or properties of the timeline. But, once we declare a variable as "var", then from that line down, the variable will be treated as a variable in the executeProcess, not a variable in the timeline. 

Where is the executeProcess ? When this function is called, system prepared a platform to execute the scripts. This platform is the scope of the variables that declared as var. If this function is called again, another platform will be created. Then the variables are created at the 
second platform. The platforms are not the same one. If in a function, we declared "var a", then there will be a platform1.a; When this function is called again, there will be platform2.a;

Where is the platform ? We dont know. It is there but not accessible. We have no way to access those "var". It is not belong to function object, so we can not access them by the handle of that function. In function myFun, we declare "var a". After myFun is called, a is created. It is not myFun.a; Nor _root.a;

Since we have no way to access those variables, it is likely we will not use them any more. The variables will be cleaned automatically by the system. So, the variables usually created during function call and disappeared after the function ends.

Exmaples of script : var in the body of function

function b() {
   
a = 4;
    trace(a);
// output 4
    var a;
    trace(a);
//output: undefined. Since here all "a" is treated as var, so it is different from this.a
    var a = 5;
    trace(a);
// output 5;
    a=6;
    trace(a);
//output 6. This a is "var a";
    var a;
    trace(a);
//output 6. It does nothing. It will not create a fresh variable "a";
}
b();
trace(a);
//output 4. Here is the "this.a", it is different from "var a";

Please note that, "var a" without assigning initial values will make variable "a" to be Process scoped. While for a variable "a" that is already declared as Process scoped, "var a" does nothing. It will not create a new Process scoped variable "a";


3.
var in nested function definitions:


Lets first see the script below before we go to discussions:

setupB = function () {
    var a = 3;
    c = 5;
    B = function () { trace(a);trace(c);};
// trace(a) output 4;
    a++;
};
setupB();
B();


Calling of "setupB" will create a function "B". Here is the problem. Action script is a "dynamically compiled language". It does not hardcode "3" to replace the "a". The body will not be changed to "trace(3);". It is still "trace(a);". When we call function B, it push a string "a" to the stack of system and then push "getVariable" to process out what is "a". Then it trace out the value of "a". 

If we believe that the variable "a" which is declared as "var", should be Process scoped and usually will diappear after the end of function call of "setupB". Then, how does function B know what is "a" ? Where will it find the "a" ? There is no "a" in timeline, nor in the function of "setupB". If "a" survives, it should be PlatForm1.a;

We have no way to access platForm1.a; However, when a function is created, the "scope" is recorded. In our example, it knows "a" is Process scoped and "c" is timeline scoped. So, it goes to platform1 to find "a". Yes, it found "a". The weird thing is: it trace out "a" as 4, because platform1.a is really 4; 

Why not "trace(a);" output 3 ? Did we expect it to be 4 ? Yes, variable "a" did not die and still survives in that platform where we execute our function. Flash does not hard code the value to function B;

Lets see another example:

setupAs = function () {
    for (var k = 0; k<6; k++) {
        this["a"+k] = function () { trace(k);};
        this["a"+k].c = k;
    }
};
setupAs();
trace(a3.c);
//output 3
a3();
//output 6;

Calling "setupAs" function will create many function objects. They will trace(k) when called. They also has a property "c" set to k;

The value of "c" is assigned directly during the fuction execution. While calling of these function object will make it dynamically analyses what is "k". All these functions results the same output: "a" as 6; Did you expect the output will be 0,1,2,3,4,5 for each ["a"+k] function ?

Personally, I would avoid this syntax. I will not pass temporary variables to the body of nested function definition. It is confusing for what we know about "var" ; If you feel confused after reading this, I think you will agree with me about this point.


4.
private property and methods


Flash MX adds many features to support OOP. It introduces the usuage of components. We may create components and give them to colleague. Or, we may take advantage of components created by others. 

Usually we will not review all the property names or methods names the author use. If there is a property or method named as "tiger" and we accidentally name our variable as "tiger", it will crash the components. Sometime, user may review the components and see a method name. User may use that method inadvently. To avoid this, author may name their properties as strange as possible to avoid conflict. The names may be "$$tiger" or "__tiger" etc. That is puzzling for both author and users. 

The other way is by setting "ASSetPropFlags", to hide the properties; However, they are only hidden and are not secure enough. 

In other language, there is a keyword "private". If a method or property is declared as "private", then user has no way to touch them. They see them but can not touch them. There is no such keyword in Flash Action script.

In the section above, we noted that, some variables can exist somewhere we can not access them freely. Only those functions can. So, some use this "side effect" to implement the "private" thing.

example:

Circle = function () {
    var $radius;
    var $getRadius = function () {
        return $radius;
    };
    var $setRadius = function (d) {
        $radius = d;
    };
    this.addProperty("radius", $getRadius, $setRadius);
    this.getArea = function() {
        return $radius*$radius*Math.PI;
    };
};
a = new Circle();
b = new Circle();
a.radius = 10;
b.radius = 20;
trace(a.radius);


Here $radius is created during function call for constructing a. It lives in the platform of this function call. It does not live in a circle. We have no way to access $radius. The only way is through the call of radius(getter/setter) function or getArea method. When we create circle b, there is another $radius in the platform of the second call. It does not conflict with what is in the plafform1.

So, $radius is like a private property and $getRadius and $setRadius are like private methods. However, this syntax is not widely used. In fact, I wont say $radius is truely a property "of circle a". It is not really compatible with prototype and inheritance.