【发布时间】:2013-09-14 20:58:44
【问题描述】:
如果你不知道我在说什么,试试这个:
<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”关键字定义的变量被放置在调用页面的变量范围内。
local 范围包含在函数执行期间使用 var 关键字或 local 范围名称(例如 local .myvar,本地[“myvar”])。它还包含 arguments 范围。
arguments 范围包含函数调用中声明或传递的每个参数。变量也可以在函数执行期间添加到其中或从中删除。 arguments 作用域是 local 作用域的成员,可以这样引用(例如 local.arguments.myvar、local.arguments[1]),但它也可以被独立引用(例如 arguments.myvar、arguments[1])。
-
有一个无名作用域,其中包含 已声明 的每个参数的副本(即包含在 cfargument 标记中,或 cfscript 中函数定义开头的括号中)。我观察到与此范围相关的以下特征和行为:
未声明的参数未添加到无名作用域。
声明参数是使变量进入无名作用域的唯一方法,ColdFusion 似乎不会在任何其他情况下使用它。
与 arguments 范围不同,无名范围与 local 范围没有明显关系。
无名作用域变量的值及其 参数 作用域对应的值要么是对同一值的引用,要么以这样一种方式相互连接,即更改一个变量会同时改变两者.
将新变量动态添加到 arguments 并 不 将其添加到无名范围(因为只有 已声明的 参数添加到无名作用域)。
您不能通过常规方式(即 StructDelete()、ArrayDeleteAt())删除无名作用域变量。您可以删除其 arguments 范围的对应项,但该值将通过无范围的引用保持可用。 (有关完全删除已声明参数的方法,请参阅 Henry 的回答)。
从 arguments 中删除声明的参数后,可以独立设置其无名范围对应项的值。即使将具有相同名称的变量添加回 arguments,这仍然适用。
CF9 和 CF10 中存在无名作用域,但(正如 Henry 和 Adam 指出的)Railo 中不存在。
-
无名作用域位于 CF 作用域层次结构的绝对顶部,在使用无作用域引用时优先于所有其他作用域。这一点,连同前面关于不可删除性的观点,可能是关于无名作用域最重要的事情。与官方文档相反,特定于功能的范围层次结构如下:
- 无名(声明的参数)
- 本地
- 参数
【问题讨论】:
标签: function coldfusion scope arguments user-defined-functions