Check out the second section in the cfm file -- you can grab a reference
directly to a method within a CFC and then use that method outside the
CFC. I tried it using the getinstancevars() method but got a "Variable
INSTANCE is undefined" error, so obviously this is being used outside
the scope of the CFC.
Is this correct (and expected) behaviour?
Yes. I believe CF5 allowed you assign a UDF to a variable and pass it around:
<cfscript>
function foo() { return 42; }
bar = foo;
x = bar();
</cfscript>(It's certainly legal in CFMX)
A function is actually compiled to a class and then instantiated so functions and methods can be passed around just like any other object. As you also discovered, when you execute the function, it *dynamically* looks up variables. This allows you to do things like this:
<!--- thing.cfc --->
<cfcomponent>
<cfset instance = structNew() />
<cffunction name="setFoo" returntype="thing">
<cfargument name="x">
<cfset instance.x = arguments.x />
<cfreturn this />
</cffunction>
<cffunction name="getFoo" returntype="any" />
<cfreturn instance.x />
</cffunction>
</cfcomponent><!--- naughty.cfm --->
<cfscript>
function hijacker() {
return instance;
}
thingie = createObject("component","thing");
thingie.naughty = hijacker;
stolenData = thingie.naughty();
</cfscript>Two things to note: a) you can create a UDF that references an (as yet) undeclared variable b) you can insert new methods into object instances (and call them)
This is a direct consequence of functions being 'objects' and the 'hijacking' of variables is a direct consequence of ColdFusion having 'dynamic binding' for variables. CF would have to be a more complex language to disallow that (it would have to introduce 'closures' - tentative binding of variables).
Note that being able to pass functions around can be very useful. Consider this example:
<cfscript>
function transform(anArray,aFunction) {
for (i = 1; i le arrayLen(anArray); i = i + 1) {
anArray[i] = aFunction(anArray[i]);
}
return anArray;
}
function twice(x) {
return x + x;
}
function thrice(x) {
return x * 3;
}
a = arrayNew(1);
a[1] = 1;
a[2] = 2;
b = transform(a,twice);
c = transform(a,thrice);
</cfscript>
<cfdump label="a doubled" var="#b#" />
<cfdump label="a trebled" var="#c#" />Being able to parameterize behavior like is very powerful.
Sean A Corfield -- http://www.corfield.org/blog/
"If you're not annoying somebody, you're not really alive." -- Margaret Atwood
----------------------------------------------------------
You are subscribed to cfcdev. To unsubscribe, send an email
to [EMAIL PROTECTED] with the word 'unsubscribe cfcdev' in the message of the email.
CFCDev is run by CFCZone (www.cfczone.org) and supported by Mindtool, Corporation (www.mindtool.com).
