Ask a Jedi: Finding where a variable is defined

This post is more than 2 years old.

Sean asks:

Do you know of a function, either built in or user defined, that will display the scope where a variable exists. I'm working with old code that does not always scope the variables and I'm having a hard time tracking some of them down.

While I'm not aware of such a function, I'm sure we can write one easily enough. Here is what I came up with.

function findScope(v) { var scopes = "arguments,variables,thread,cgi,cffile,url,form,cookie,client"; var s = ""; var ptr = ""; var i = 1;
for(;i < listLen(scopes); i++) {
	s = listGetAt(scopes,i);
	ptr = structGet(s);
	if(structKeyExists(ptr, v)) return s;
}

return "";

}

This UDF works with a predefined list of scopes based on the scopes that ColdFusion will check when you do not define a scope. (More on this here.) This isn't an exact match to the list ColdFusion checks as some of them are unnamed. Also, you may want to extend this list to include Application and Session. Those scopes are not checked with unscoped variables, but if you want, just add them to the list.

Once we have our list, the rest of the code isn't too exciting. We loop over each scope and use structGet to get a pointer to the scoper. We then do a simple structKeyExists and if the key exists, we return the scope name. Here is a simple test script I wrote to demonstrate the UDF in action:

<cfset variables.x = 1> <cfset url.y = 2> <cfset form.z = 3> <cfset cookie.a = 'peanut butter jelly'>

<cfoutput> findScope('x')=#findScope('x')#<br /> findScope('y')=#findScope('y')#<br /> findScope('z')=#findScope('z')#<br /> findScope('a')=#findScope('a')#<br /> findScope('idontexist')=#findScope('idontexist')# </cfoutput>

Note - this UDF will only work in ColdFusion 8 because of the < and ++. You can modify that easily enough. Frankly now that I've got these in cfscript under CF8 I'm going to use them everywhere I can! You would also need to remove the thread value from the list.

Raymond Camden's Picture

About Raymond Camden

Raymond is a senior developer evangelist for Adobe. He focuses on document services, JavaScript, and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA https://www.raymondcamden.com

Archived Comments

Comment 1 by Gert Franz posted on 10/10/2008 at 6:37 PM

Hi folks,

in Railo 3 you can do that with the function getMetaData().
Just pass a variable string and add a second parameter (true) to it. So the following:
<cfdump var="#getMetaData("myVar", true)#">
Displays all the scopes that the variable myVar exists in.
http://www.railo-technologi...

Gert

Comment 2 by Raymond Camden posted on 10/10/2008 at 7:35 PM

And you should point out - R3 also allows you to block scope lookup. So if X isn't defined in Variables, your engine won't start looking up the scopes. This is something I hope Adobe adds as well.

Comment 3 by Tim Smolders posted on 2/26/2015 at 12:09 PM

for(;i <= listLen(scopes); i++)

Add '=', otherwise never returns client scope.

Comment 4 (In reply to #3) by Raymond Camden posted on 2/26/2015 at 2:12 PM

Good point. Thanks!