isDefined() tries very hard to find any possible definition of the requested variable. It searches through the scopes as if the variable name is not scope-qualified - even when it contains a dot (.) which seems to date back to pre-MX ColdFusion which allowed dots in variable names. For example, if you say:
<cfset variables.variables.foo = 42 />
you may be surprised to discover that isDefined("variables.foo") is YES, even tho' there is no variable called foo in the variables scope. If you say isDefined("foo") and foo is a URL scope variable, you'll get YES (unqualified scope lookup) but if you say isDefined("x.foo") you'll get NO even if x.foo is passed in the URL - you need isDefined("url.x.foo") for that. Buggy? Perhaps. Confusing? Certainly! In all cases, structKeyExists() lets you test for variable existence much more precisely:
structKeyExists(variables,"foo") is NO
structKeyExists(variables,"variables") is YES
structKeyExists(variables.variables,"foo") is YES
(for the examples above).structKeyExists(variables,"variables") is YES
structKeyExists(variables.variables,"foo") is YES

33 responses so far ↓
1 Ryan Guill // Sep 8, 2004 at 5:04 PM
2 Giampaolo Bellavite // Sep 8, 2004 at 5:04 PM
3 Sean Corfield // Sep 8, 2004 at 5:04 PM
4 PaulKD // Sep 8, 2004 at 5:04 PM
5 dgibson // Sep 8, 2004 at 5:04 PM
6 Larry // Sep 8, 2004 at 5:04 PM
7 Sean Corfield // Sep 8, 2004 at 5:04 PM
8 Laurence // Sep 8, 2004 at 5:04 PM
9 Sean Corfield // Sep 8, 2004 at 5:04 PM
10 James Holmes // Sep 8, 2004 at 5:04 PM
11 David McLean // Aug 23, 2006 at 6:31 AM
12 Sean Corfield // Aug 23, 2006 at 8:02 AM
13 David McLean // Aug 23, 2006 at 8:26 AM
14 Sean Corfield // Aug 23, 2006 at 10:26 AM
15 David McLean // Aug 23, 2006 at 1:11 PM
16 Ryan Stewart // Oct 23, 2006 at 1:13 AM
--
Wouldn't this be written:
StructKeyExist(variables.test,"foo") ?
17 Sean Corfield // Oct 23, 2006 at 7:44 AM
structKeyExists(variables,"test") and structKeyExists(variables.test,"foo")
You need both.
18 William Broadhead // Apr 3, 2007 at 6:09 PM
Short answer: structKeyExists is SLOWER and has no advantage other than forcing coder to use scoping, which s/he should do anyway...
Long Answer:
whereas for the examples below url.pageid is a real url variable
STRUCTKEYEXISTS:
structKeyExists is pretty much the same speed no matter what you throw at it, keys can be real or not (url, 'pageid' and url, 'pageadfasdf' are about the same, no big diff one way or the other)
and if you throw a scope at it that does not exist, it throws, so it forces you to be careful about scoping.
ISDEFINED:
isDefined is super fast when the scope exists and you pass in a scope (url.pageid),
however, it is extremely extremely mega super slow when you pass in a non-existant scope (urlss.pageid).
it is also super super mega slow if you pass in a non-scoped non-existant variable (pagelksjdljsdf)
it is quite fast, on average 10 to 20% faster than structKeyExists, when you pass in a SCOPED variable, existant or not (url.pageid or url.aoiausldkjf)
So what does that mean in real life?
Well, as long as you are asking for a SCOPED variable that is extant, and you don't mispell the scope (url for instance), isDefined will be faster on average....
If you are looking for a NON-SCOPED variable, you have no choice but to live with isDefined.... hum....which can be very very slow when the variable does not exist.
If you want to make sure you scope all your vars, use structKeyExists and live with a small speed hit, but be assured it is scoped to a real scope (or throw an error).
So for me, in real life use, that means isDefined is probably the better choice as it is overall going to be faster as long as i can spell my scope correctly.
It also is the only choice to use when looking for multiple scope variables such as FORM.ID vs URL.ID and your page/function can take either and want to simply ask isDefined('ID')
but if you want to prioritize one over the other (which you probably should) then you can again use either define/struct
where you have a little bit of script that checks each (form.id and then url.id) and assigns a variables.myID which is then passed in to page/function to use....
again, this would indicate isDefined would be preferred as it would be faster for that call too, as long as it is scoped and the scope exists.
So I can't find any reason to use structKeyExists other than it might seem like better code because it forces scoping....
How sad... it seemed like it should be faster as it specifies the scope....
here is sample code for you to run and see for yourself.... i'd love to know if you find anything different than what I did by platform or other (I am using CFMX702 on a WINDOWS platform). Is linux version any faster? Anyone know what actually happens at the compiled java level?)
<CFSCRIPT>
ITERATIONS = 100000;
writeoutput('ITERATIONS : ' & ITERATIONS & '<BR>' );
i=0;
j=0;
k=0;
ttt1 =0;
ttt2 =0;
t1c =0;
t2c=0;
for(k; k lte ITERATIONS; k=k+1){
T1 = getTickCount();
for(i; i lte ITERATIONS; i=i+1){
if(isdefined('url.asdfpageid')){
//do nothing
}
}
T2 = getTickCount();
TT1 = T2-T1;
ttt1=ttt1+TT1;
T3 = getTickCount();
for(j; j lte ITERATIONS;j=j+1){
if(structKeyExists(url, 'pageeid')){
//do nothing
}
}
T4 = getTickCount();
TT2 = T4-T3;
ttt2=ttt2+TT2;
if(TT1 gt 0){t1c = t1c+1;}
if(TT1 gt 0){t2c = t2c+1;}
if(TT1 gt 0 or TT2 gt 0){writeoutput('Iteration K: ' & k & ' isDefined: ' & TT1 & 'ms'); writeoutput(' structKeyExists: ' & TT2 & 'ms<br>');}
}
writeoutput('<BR>Times isDefined used time: ' & t1c);
writeoutput('<BR>Times structKeyExists used time: ' & t2c);
writeoutput('<BR>FINAL isDefined: ' & TTT1 & 'ms');
writeoutput('<BR>FINAL structKeyExists: ' & TTT2 & 'ms');
</CFSCRIPT>
<br>
<!--- The cfchart --->
<cfchart format="flash" xaxistitle="function" yaxistitle="Loading Time">
<cfchartseries type="bar" serieslabel="isDefined">
<cfchartdata item="isDefined" value="#variables.TTT1#">
</cfchartseries>
<cfchartseries type="bar" serieslabel="structKeyExists">
<cfchartdata item="structKeyExists" value="#variables.TTT2#">
</cfchartseries>
</cfchart>
19 Sean Corfield // Apr 3, 2007 at 10:15 PM
20 William Broadhead // Apr 4, 2007 at 1:12 PM
21 William Broadhead // Apr 4, 2007 at 2:34 PM
2 sets of runs, 15 run throughs, not a single instance of structKeyExists as faster...
i'll post the code and results in two following posts.
22 William Broadhead // Apr 4, 2007 at 2:36 PM
<CFSCRIPT>
ITERATIONS = 1000000;
writeoutput('ITERATIONS : ' & ITERATIONS & '<BR>' );
i=0;
j=0;
k=0;
ttt1 =0;
ttt2 =0;
t1c =0;
t2c=0;
for(k; k lte ITERATIONS; k=k+1){
T1 = getTickCount();
for(i; i lte ITERATIONS; i=i+1){
if(isdefined('url.pageid')){
//do nothing
}
}
T2 = getTickCount();
TT1 = T2-T1;
ttt1=ttt1+TT1;
T3 = getTickCount();
for(j; j lte ITERATIONS;j=j+1){
if(structKeyExists(url, 'pageid')){
//do nothing
}
}
T4 = getTickCount();
TT2 = T4-T3;
ttt2=ttt2+TT2;
if(TT1 gt 0){t1c = t1c+1;}
if(TT2 gt 0){t2c = t2c+1;}
if(TT1 gt 0 or TT2 gt 0){writeoutput('Iteration K: ' & k & ' isDefined: ' & TT1 & 'ms'); writeoutput(' structKeyExists: ' & TT2 & 'ms<br>');}
}
writeoutput('<BR>Times isDefined used time: ' & t1c);
writeoutput('<BR>Times structKeyExists used time: ' & t2c);
writeoutput('<BR>FINAL isDefined: ' & TTT1 & 'ms');
writeoutput('<BR>FINAL structKeyExists: ' & TTT2 & 'ms');
if(TTT1 GT TTT2){
writeoutput('<BR>structKeyExists is faster by: ' & TTT1-TTT2 & 'ms which is ' & NUMBERFORMAT((TTT1-TTT2)/TTT1*100, '9.9') & '% faster');
}else{
writeoutput('<BR>isDefined is faster by: ' & TTT2-TTT1 & 'ms which is ' & NUMBERFORMAT((TTT2-TTT1)/TTT2*100, '9.9') & '% faster' );
}
</CFSCRIPT>
<br>
<!--- The cfchart --->
<cfchart format="flash" xaxistitle="function" yaxistitle="Loading Time">
<cfchartseries type="bar" serieslabel="isDefined">
<cfchartdata item="isDefined" value="#variables.TTT1#">
</cfchartseries>
<cfchartseries type="bar" serieslabel="structKeyExists">
<cfchartdata item="structKeyExists" value="#variables.TTT2#">
</cfchartseries>
</cfchart>
23 William Broadhead // Apr 4, 2007 at 2:37 PM
Times isDefined used time: 107
Times structKeyExists used time: 118
FINAL isDefined: 4925ms
FINAL structKeyExists: 5641ms
isDefined is faster by: 716ms which is 12.7% faster
Times isDefined used time: 123
Times structKeyExists used time: 136
FINAL isDefined: 5255ms
FINAL structKeyExists: 5626ms
isDefined is faster by: 371ms which is 6.6% faster
Times isDefined used time: 104
Times structKeyExists used time: 138
FINAL isDefined: 5792ms
FINAL structKeyExists: 6002ms
isDefined is faster by: 210ms which is 3.5% faster
Times isDefined used time: 148
Times structKeyExists used time: 150
FINAL isDefined: 6221ms
FINAL structKeyExists: 6375ms
isDefined is faster by: 154ms which is 2.4% faster
Times isDefined used time: 349
Times structKeyExists used time: 318
FINAL isDefined: 21747ms
FINAL structKeyExists: 23098ms
isDefined is faster by: 1351ms which is 5.8% faster
Times isDefined used time: 271
Times structKeyExists used time: 325
FINAL isDefined: 14802ms
FINAL structKeyExists: 31557ms
isDefined is faster by: 16755ms which is 53.1% faster
Times isDefined used time: 300
Times structKeyExists used time: 293
FINAL isDefined: 25496ms
FINAL structKeyExists: 35296ms
isDefined is faster by: 9800ms which is 27.8% faster
Times isDefined used time: 333
Times structKeyExists used time: 271
FINAL isDefined: 22676ms
FINAL structKeyExists: 26463ms
isDefined is faster by: 3787ms which is 14.3% faster
Times isDefined used time: 245
Times structKeyExists used time: 268
FINAL isDefined: 11288ms
FINAL structKeyExists: 15934ms
isDefined is faster by: 4646ms which is 29.2% faster
Times isDefined used time: 220
Times structKeyExists used time: 267
FINAL isDefined: 11470ms
FINAL structKeyExists: 16012ms
isDefined is faster by: 4542ms which is 28.4% faster
Times isDefined used time: 266
Times structKeyExists used time: 281
FINAL isDefined: 10572ms
FINAL structKeyExists: 13946ms
isDefined is faster by: 3374ms which is 24.2% faster
Times isDefined used time: 278
Times structKeyExists used time: 275
FINAL isDefined: 10125ms
FINAL structKeyExists: 13329ms
isDefined is faster by: 3204ms which is 24.0% faster
Times isDefined used time: 242
Times structKeyExists used time: 253
FINAL isDefined: 10067ms
FINAL structKeyExists: 14494ms
isDefined is faster by: 4427ms which is 30.5% faster
Times isDefined used time: 192
Times structKeyExists used time: 221
FINAL isDefined: 7526ms
FINAL structKeyExists: 12226ms
isDefined is faster by: 4700ms which is 38.4% faster
Hum...on my random pulls, i usually see about 1 in 10 where structKeyExists is faster, but this particular series (ran in 5 windows 3 times each concurrently, thus under some load), I didn't get any...
15 pulls where scope and key exist.
Times isDefined used time: 312
Times structKeyExists used time: 317
FINAL isDefined: 7706ms
FINAL structKeyExists: 8730ms
isDefined is faster by: 1024ms which is 11.7% faster
Times isDefined used time: 311
Times structKeyExists used time: 338
FINAL isDefined: 8596ms
FINAL structKeyExists: 17218ms
isDefined is faster by: 8622ms which is 50.1% faster
Times isDefined used time: 326
Times structKeyExists used time: 314
FINAL isDefined: 12959ms
FINAL structKeyExists: 16560ms
isDefined is faster by: 3601ms which is 21.7% faster
Times isDefined used time: 301
Times structKeyExists used time: 275
FINAL isDefined: 12339ms
FINAL structKeyExists: 16680ms
isDefined is faster by: 4341ms which is 26.0% faster
Times isDefined used time: 298
Times structKeyExists used time: 322
FINAL isDefined: 12346ms
FINAL structKeyExists: 17918ms
isDefined is faster by: 5572ms which is 31.1% faster
Times isDefined used time: 350
Times structKeyExists used time: 347
FINAL isDefined: 12619ms
FINAL structKeyExists: 17863ms
isDefined is faster by: 5244ms which is 29.4% faster
Times isDefined used time: 358
Times structKeyExists used time: 331
FINAL isDefined: 12248ms
FINAL structKeyExists: 18148ms
isDefined is faster by: 5900ms which is 32.5% faster
Times isDefined used time: 374
Times structKeyExists used time: 363
FINAL isDefined: 9712ms
FINAL structKeyExists: 12739ms
isDefined is faster by: 3027ms which is 23.8% faster
Times isDefined used time: 320
Times structKeyExists used time: 355
FINAL isDefined: 15134ms
FINAL structKeyExists: 19300ms
isDefined is faster by: 4166ms which is 21.6% faster
Times isDefined used time: 314
Times structKeyExists used time: 324
FINAL isDefined: 14377ms
FINAL structKeyExists: 19059ms
isDefined is faster by: 4682ms which is 24.6% faster
Times isDefined used time: 291
Times structKeyExists used time: 349
FINAL isDefined: 13776ms
FINAL structKeyExists: 21890ms
isDefined is faster by: 8114ms which is 37.1% faster
Times isDefined used time: 360
Times structKeyExists used time: 351
FINAL isDefined: 13814ms
FINAL structKeyExists: 23769ms
isDefined is faster by: 9955ms which is 41.9% faster
Times isDefined used time: 244
Times structKeyExists used time: 247
FINAL isDefined: 9884ms
FINAL structKeyExists: 14090ms
isDefined is faster by: 4206ms which is 29.9% faster
Times isDefined used time: 293
Times structKeyExists used time: 266
FINAL isDefined: 9830ms
FINAL structKeyExists: 13967ms
isDefined is faster by: 4137ms which is 29.6% faster
Times isDefined used time: 312
Times structKeyExists used time: 315
FINAL isDefined: 8854ms
FINAL structKeyExists: 11584ms
isDefined is faster by: 2730ms which is 23.6% faster
hum... well... not sure what to say. even worse than what i get on my development machine.
24 Sean Corfield // Apr 4, 2007 at 3:25 PM
Times isDefined used time: 786
Times structKeyExists used time: 746
FINAL isDefined: 2278ms
FINAL structKeyExists: 1790ms
structKeyExists is faster by: 488ms which is 21.4% faster
25 Jake Astle // Apr 4, 2007 at 4:17 PM
26 Jeff Gladnick // Apr 20, 2009 at 11:30 AM
27 Sean Corfield // Apr 20, 2009 at 11:54 AM
As I said in several places, I've had specific problems with isDefined() so I avoid it - except in the one case where I've needed it: for testing against null in the result of a method call:
var res = obj.someMethod(args);
if ( isDefined('res') ) ...
Currently there's no other way to test for null results (in ColdFusion, at least).
28 Mark // May 6, 2009 at 5:56 PM
<cffunction name="onRequest" returntype="boolean">
<cfargument name="targetPage" type="string" required="true" />
<cfif isUserLoggedIn()>
<cfif not structKeyExists(session,"user")>
<!--- do something --->
<cfinclude template="test.cfm">
<cfelse>
<cfinclude template="#arguments.targetPage#">
</cfif>
</cfif>
<cfreturn true />
</cffunction>
behave so differently from this:
<cffunction name="onRequest" returntype="boolean">
<cfargument name="targetPage" type="string" required="true" />
<cfif isUserLoggedIn()>
<cfif not isDefined(session.user)>
<!--- do something --->
<cfinclude template="test.cfm">
<cfelse>
<cfinclude template="#arguments.targetPage#">
</cfif>
</cfif>
<cfreturn true />
</cffunction>
29 Sean Corfield // May 6, 2009 at 6:05 PM
Second, you don't say how those two pieces of code behave "so differently" so it is hard to tell what you're asking...
30 Eapen // Sep 8, 2010 at 2:50 AM
I want to test if a struct key exists in another struct key that may or may not exist.
i.e.
I want to test for variables.variablesS.test
but variables.variablesS may or may not exist.
Just wanted to find out if there is an easier way to do this? (where variables.variablesS does not exist)
With IsDefined, I could do
IsDefined("variables.variablesS.test")
but with structKeyExists, I would have to do:
StructKeyExists(variables, "variablesS") AND StructKeyExists(variables.variablesS, "test").
Is there an easier way to do this - since we can't do the following:
StructKeyExists(variables, "variablesS.test")
31 jfrobishow // Nov 10, 2010 at 1:53 PM
Try (I didn't test it, but it make sense in my head :P)
StructKeyExists(variables["variablesS"], "test")
32 Sean Corfield // Nov 10, 2010 at 3:01 PM
Also variables["variablesS"] is equivalent to variables.variablesS anyway.
33 jfrobishow // Nov 10, 2010 at 3:05 PM
Ah got me there, I knew I should have tested that before posting, hehe ;)
Leave a Comment