If I have a function like
<cfscript>
function say(what) {
var a = what;
variables.b = what;
return what;
}
</cfscript>
I thought the scope of a was variables
, but dumping variables
returns just b
. What is the scope of a?
This really is a comment, but it is way too long. Consider the following code
<cfscript>
function doMath() {
var a = 1;
local.b = 2;
return a + local.b;
}
</cfscript>
At first glance on might think that var
and local.
have the same scope. After all they both exist only within the function. When then function is done, both variables cease to exist. End of story? Maybe not.
In ColdFusion, we have both implied scopes and implicit scopes.
url.a
form.a
cookie.a
session.a
application.a
local.a
arguments.a
myQuery.a
Are all different. If I have all of the above as valid variables and I say <cfoutput>#a#</cfoutput>
which a
do I get? ColdFusion goes through its list of implied scopes until it hit one that matches. And that is the one that gets displayed. So back to the question.
So when I am inside of a function, if I use var
I am saying to ColdFusion, look through all the implied scopes until you find one that matches. If I use local.a
, I am saying look in exactly one place and use that.
Benefits
I know exactly what variable I am picking up. If you are writing code that needs to be as fast as possible you won't use implicit scopes. If you are writing code that is the most readable, you won't use implicit scopes.
So no. var
is not the same as local.
Understanding scoping can help you avoid some issues that can be extremely difficult to track down. For all intents an purposes, var a
puts a
into the local
scope, and it can be referenced as a local
variable. And if declared afterwards, it will overwrite any a
variable already in the local
scope.
https://trycf.com/gist/faf04daa53194a5fad2e69e164518299/acf2016?theme=monokai
<cfscript>
function say() {
local.a = "local" ;
var b = "var" ;
lv = local.b ; // We didn't explicitly assign b to Local scope.
try {
v = variables ; // Let's dump the variables scope.
} catch (any e) {
v = "Error: " & e.message ;
}
variables.nh = "Now here." ; // Explicitly populate variables scope.
var c = "var c" ; // We have a variables scope, what happens to var?
try {
v2 = variables ; // Let's dump the variables scope.
} catch (any e) {
v2 = "Error: " & e.message ;
}
var d = "var" ;
local.d = "local" ;
local.e = "local" ;
var e = "var" ;
return {
a : a , // Local.
b : b , // Var.
d : d , // Which one?
e : e , // Which one?
el : local.e , // Which one??
l : lv , // Ref b in local scope.
l2 : local , // Dump local scope.
v : v , // There doesn't seem to be a variables scope yet.
v2 : v2 // Defined a variable scope and now here.
} ;
}
writeDump(say());
</cfscript>
We can see above that declaring var b
puts b
into the local
scope, and that the variables
scope doesn't exist until we declare something into it. We can reference local.b
, but variables.b
can't exist. After we explicitly created and populated variables
scope with nh
, we create a var c
. This doesn't go into the variables
scope either, but into the local
scope.
When a variable is declared with the same name in either local
or by var
, the last one declared will overwrite the other one (see d
,e
and el
). Watch out for this.
Also note that the empty arguments
scope from the function is also in the local
scope.
On that note, my last two observation of scope things to watch out for:
https://trycf.com/gist/65b73e7a57d0434049d0eb9c0d5f9687/acf11?theme=monokai
<cfscript>
function ks() {
variables.jay = "Snoogins." ; // variables scope leaks out of function.
local.silentbob = "____" ; // local scope stays inside function.
}
function sayArgs(arg) {
local.arg = "local" ; // Order after agruments in CF10 but not 2016.
ks() ; // Run ks() function to instantiate jay and silentbob.
return {
arg : arg , // CF10 = arguments scope. CF11+ = local scope.
args : arguments ,
local : local , // No leakage from ks().
vars : variables // Jay leaks from ks().
} ;
}
writeDump(sayArgs("argue")) ;
</cfscript>
Two things I noted here:
First, there is a difference between the order of evaluation of arguments
and local
scopes in CF10 vs later CF versions. Current CF2016 (or 2011+) behavior is that local
scope inside of a function will not overwrite the arguments
scope, but it will be evaluated first. The opposite happens in CF10: arguments
is evaluated first. Lucee and Railo behave like ACF2016.
The second note has to do with variable leakage as it applies to variables
and local
. local
will only exist inside the function that it is declared in. variables
is more global and can be reached outside of the function.
https://helpx.adobe.com/coldfusion/developing-applications/the-cfml-programming-language/using-coldfusion-variables/about-scopes.html << For ACF2016. Displays evaluation order with local
over arguments
.
http://www.learncfinaweek.com/week1/Scopes/ << Lists the order that ACF10 evaluates in, but the order of arguments
and local
are switched in later versions.
https://help.adobe.com/en_US/ColdFusion/9.0/Developing/WSc3ff6d0ea77859461172e0811cbec09af4-7fdf.html << This is the documentation for ACF9. It lists the same order as ACF2016, but is different in ACF10. I don't have a copy of CF9 to test against right now, so I don't know how CF9 and earlier handle the evaluations.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With