有没有办法直接与CF9 / 10中无名声明的参数范围进行交互?

时间:2013-09-11 00:43:05

标签: function coldfusion scope arguments user-defined-functions

如果你不知道我在说什么,试试这个:

<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范围的理解的细分可能是有用的,因为亚当的反应有点模糊了这些线条。为简单起见,我将排除特定于cfc的内容......

  • 没有范围或“var”关键字定义的变量放在调用页面的变量范围内。

  • local 范围包含使用 var 关键字或本地范围名称(例如本地)在函数执行期间创建的变量.myvar,local [“myvar”])。它还包含参数范围。

  • arguments 范围包含在函数调用中声明或传递的每个参数。在函数执行期间,也可以向其添加或删除变量。 参数范围是 local 范围的成员,可以这样引用(例如local.arguments.myvar,local.arguments [1]),但它也可能独立引用(例如arguments.myvar,arguments [1])。

  • 有一个无名范围包含声明的每个参数的副本(即包含在cfargument标记中,或者在cfscript中函数定义开头的括号中) 。我观察到以下与此范围相关的特征和行为:

    • 未声明的参数未添加到无名范围。

    • 声明参数是将变量放入无名范围的唯一方法,ColdFusion似乎不会在任何其他情况下使用它。

    • arguments 范围不同,无名范围与本地范围没有明显关系。

    • 无名范围变量及其参数 -scoped副本的值是对相同值的引用,或者是以这样一种方式相互连接,即更改一个变量

    • 参数动态添加新变量 将其添加到无名范围(因为只有声明的参数被添加到无名范围。)

    • 您无法通过常规方式删除无名范围变量(即StructDelete(),ArrayDeleteAt())。您可以删除其参数 -scoped对应项,但该值将通过未作用域的引用保持可用。 (有关完全删除已声明参数的方法,请参阅Henry的答案。)

    • 参数中删除声明的参数后,可以单独设置其无名范围对应的值。即使将具有相同名称的变量添加回参数,这仍然是正确的。

    • 无名范围存在于CF9和CF10中,但(正如Henry和Adam指出的那样)不在Railo中。

    • 无名范围位于CF的范围层次结构的绝对顶部,在使用未范围的引用时优先于所有其他范围。这一点,以及早先关于不可充分性的观点,可能是关于无名范围的最重要的事情。与官方文档相反,特定于功能的范围层次结构是:

      1. 无名(声明的参数)
      2. 本地
      3. 参数

2 个答案:

答案 0 :(得分:2)

在ColdFusion中,所有参数都在每个函数开头的未命名函数局部作用域中重复。这段代码:

<cfset writeOutput("myArg still exists, and evaluates to: " & myArg)>

不访问参数范围,它正在访问函数本地范围。如果您更改了代码以访问参数范围,您将 - 毫不奇怪 - 看到该变量不再存在。

顺便提一下,Railo的行为并不像这样。

答案 1 :(得分:1)

有趣的是,这个测试用例有一个非常奇怪的行为。我不知道为什么myArg仍然可用。但是,如果您对var进行范围调整并执行此操作:

<cfset writeOutput("myArg still exists, and evaluates to: " & arguments.myArg)>

或者,如果不是structDelete(),请将其设置为null

<cfset myArg = javacast("null","")>

然后你会得到"myArg no longer exists"

这可能是Adobe CF优化的边缘情况。 Railo按预期运行,预期结果。您可以在http://cflive.net/

上自行测试