April 19, 2012

Scope precedence (from function perspective)

Scoping. Very common topic among CF developers.
Which scope has precedence? When and why I should scope variable?
No matter how many times I read or heard answer on these question, no matter how many I answered to myself, I always forget it after few months.
Thus I decided to find a way how to remember it once and for all :)
Magic formula (for me) is in answer: "Scope precedence is same as it is in Java"
Here I talk only about precedence from function perspective.
Inside method (function) body we deal with 3 major scopes (fake this I'll ignore)

Argument scope - hold references to function arguments
Local scope - hold references to local variables, variables declared (vared) inside function body
Variables scope - it contains references to protected instance variables

In same order scopes are listed here, Adobe ColdFusion 9.x (and I beleive Railo 3.x) will go through when looking for variable referenced inside function body. This means:
Referenced variable, which is not explicitally scoped inside function body, ACF first look for in argument scope, then if it could not be found there, in local and, at the end, in variable scope.

At the same time, we should have 2 things in mind :
1) Local variable cannot be named same as argument (same as in Java)
2) CF, as dynamic language with weak typing, allows dynamic argument list which means, that argument does not need to be defined, unless it is explicitly set (required = true)

Example 1: Argument value not set

//ScopingTest.cfc
component{
 myVar = "instance variable value";
 
 //no default value set for argument myVar
 function myMethod(myVar){
  myVar = myVar;
  writeOutput(myVar);
 }
}

//call
new ScoptinTest().myMthod();

//output
"instance variable value"

Example 2: Argument value set

//call
new ScoptinTest().myMethod("argument value");

//output
"argument value"

From these examples, we clearly see, if we don't explicitly scope variable:
a) If argument is not defined, instance variable will take presedence
b) If argument is defined, it is going to take presedence

To summarize:
1. Argument and Local variables shares the throne (there can be only one)
2. Variable comes right after

Knowing this, much less characters we'll write in the future and much less noise in the code.