Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scope of var and variables

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?

like image 880
Manaus Avatar asked Dec 24 '22 12:12

Manaus


2 Answers

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.

like image 86
James A Mohler Avatar answered Feb 03 '23 22:02

James A Mohler


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>

Output 1

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>

Output 2

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.

like image 36
Shawn Avatar answered Feb 03 '23 22:02

Shawn