如果你不知道我在说什么,试试这个:
<cffunction name="myFunc">
<cfargument name="myArg" default="foobar">
<cfdump var="#local#" label="local and arguments scopes before deleting myArg">
<cfset StructDelete(arguments, "myArg")>
<cfdump var="#local#" label="local and arguments scopes after deleting myArg">
<cfset StructDelete(local, "arguments")>
<cfdump var="#local#" label="local scope after deleting arguments scope">
<cftry>
<cfset writeOutput("myArg still exists, and evaluates to: " & myArg)>
<cfcatch>
<cfset writeOutput("myArg no longer exists")>
</cfcatch>
</cftry>
</cffunction>
<cfset myFunc()>
<cfexit>
如果您运行该代码,您会发现即使在删除参数和参数范围之后,您仍然可以通过非范围引用访问声明的参数。这意味着存在一个未命名的范围,其中包含声明的参数的副本或值的引用。我试图找出是否有某种方法可以直接使用此范围,例如未记录的范围名称或底层 Java 中的 getter 方法。现在考虑这是一个纯粹的学术问题,因为我很确定我可能想到的任何用例都会被大多数有声望的程序员忽略掉。
编辑
我认为提供我目前对 UDF 范围的理解的细分可能很有用,因为 Adam 的反应有点模糊了界限。为简单起见,我将排除特定于 cfc 的内容...
没有范围或“var”关键字定义的变量被放置在调用页面的变量范围中。
局部作用域包含在函数执行期间使用var关键字或局部作用域名称(例如 local.myvar、local["myvar"])创建的变量。它还包含参数范围。
arguments范围包含在函数调用中声明或传递的每个参数。变量也可以在函数执行期间添加到其中或从中删除。arguments作用域是本地作用域的成员,可以这样引用(例如 local.arguments.myvar、local.arguments[1]),但也可以单独引用(例如 arguments.myvar、arguments[1]) .
有一个无名作用域,其中包含声明的每个参数的副本(即包含在 cfargument 标记中,或 cfscript 中函数定义开头的括号中)。我观察到与此范围相关的以下特征和行为:
未声明的参数不会添加到无名范围。
声明参数是使变量进入无名作用域的唯一方法,ColdFusion 似乎不会在任何其他情况下使用它。
与参数作用域不同,无名作用域与局部作用域没有明显关系。
无名范围变量的值及其参数范围对应的值要么是对相同值的引用,要么以这样一种方式相互连接,即改变一个会改变两者。
将新变量动态添加到参数不会将其添加到无名范围(因为只有声明的参数才会添加到无名范围)。
您不能通过常规方式(即 StructDelete()、ArrayDeleteAt())删除无名范围的变量。您可以删除其arguments范围的对应项,但该值将通过无范围的引用保持可用。(有关完全删除已声明参数的方法,请参见亨利的回答)。
一旦从arguments中删除了已声明的参数,就可以独立设置其无名范围对应项的值。即使将具有相同名称的变量添加回arguments ,这仍然是正确的。
CF9 和 CF10 中存在无名范围,但(正如 Henry 和 Adam 指出的)Railo 中没有。
无名作用域位于 CF 作用域层次结构的绝对顶部,在使用无作用域引用时优先于所有其他作用域。这一点,连同前面关于不可删除性的观点,可能是关于无名作用域最重要的事情。与官方文档相反,特定于功能的范围层次结构如下:
- 无名(声明的参数)
- 当地的
- 论据