ColdFusion:在CFC中省略variables关键字是否安全?

时间:2008-09-12 15:57:05

标签: coldfusion cfc

在ColdFusion组件(CFC)中,是否有必要对变量范围的变量使用完全限定名称?

如果我改变这个,我会不会遇到麻烦:

<cfcomponent>
    <cfset variables.foo = "a private instance variable">

    <cffunction name = "doSomething">
        <cfset var bar = "a function local variable">
        <cfreturn "I have #variables.foo# and #bar#.">
    </cffunction>
</cfcomponent>

到此?

<cfcomponent>
    <cfset foo = "a private instance variable">

    <cffunction name = "doSomething">
        <cfset var bar = "a function local variable">
        <cfreturn "I have #foo# and #bar#.">
    </cffunction>
</cfcomponent>

9 个答案:

答案 0 :(得分:10)

创建变量时指定“变量”无关紧要,因为默认情况下foo将放在变量范围内;但是当你访问变量时它会很重要。

<cfcomponent>
    <cfset foo = "a private instance variable">

    <cffunction name="doSomething">
        <cfargument name="foo" required="yes"/>
        <cfset var bar = "a function local variable">
        <cfreturn "I have #foo# and #bar#.">
    </cffunction>

    <cffunction name="doAnotherThing">
        <cfargument name="foo" required="yes"/>
        <cfset var bar = "a function local variable">
        <cfreturn "I have #variables.foo# and #bar#.">
    </cffunction>

</cfcomponent>

doSomething(“args”)返回“我有 args 函数局部变量

doAnotherThing(“args”)返回“我有变量的私有实例函数局部变量。”

答案 1 :(得分:6)

我会说是的。这显然是必要的吗?不。你可以逃避不做吗?当然。你在找麻烦吗?绝对。如果你在cffunction中有以下内容:

<cfset foo = "bar" />

这不会将该变量放在函数local var scope中,它会将它放在CFC的全局VARIABLES范围内,这意味着它可用于该CFC的每个方法。有时您可能想要这样做,但大多数时候您会要求竞争条件。

当服务器正在读取任何变量时,如果该变量不是声明为作用域的一部分(REQUEST。,SESSION。等),那么ColdFusion将运行ScopeCheck()来确定变量所在的范围。这不仅会给你的应用服务器带来不必要的开销,还会引入劫持的能力,你的变量在一个范围内,但是ScopeCheck()在优先顺序中找到了一个同名的变量。

始终,始终,始终,范围所有变量。无论多么微不足道。甚至包括查询名称和循环索引。从痛苦中拯救自己,以及那些来到你身后的人。

答案 2 :(得分:5)

特别是在CFC中,适当的范围很重要。额外的“冗长”值得清晰。 将变量从其入侵范围中移除将导致严重问题并且很难诊断。

冗长并不总是坏事。我们以getAuthenticatedUser()等描述方式命名我们的函数和方法,而不是gau()。数据库列和表最好是描述性的,如EmployeePayroll而不是empprl。因此,当您的短期记忆充满项目细节时,简洁可能会“更容易”,但描述性显示您的意图并且在应用程序的维护阶段有用,在您的短期记忆充满其他东西很久之后

答案 3 :(得分:3)

对你的问题的简短回答是,不,你可能不会在尝试这样做时遇到麻烦。在UDF的上下文之外(甚至仍然在CFC中),无范围的set语句意味着变量范围。

此外,在CFC中,变量范围可用于其所有功能;它是CFC中的全局范围 - 类似于“this”范围,除了变量范围类似于“私有”变量,而此范围类似于公共变量。

要测试它,请创建test.cfc:

<cfcomponent>
    <cfset foo = "bar" />
    <cffunction name="dumpit" output="true">
        <cfdump var="#variables#" label="cfc variables scope">
        <cfdump var="#this#" label="cfc this scope">
    </cffunction>
</cfcomponent>

和一个测试它的页面,test.cfm:

<cfset createObject("component", "test").dumpit() />

结果将是:


现在,为了解决我在示例代码中看到的另一个问题...

在CF中,所有用户定义函数都有一个特殊的未命名范围,通常称为“var”范围。如果在UDF中执行以下操作:

<cfset foo = "bar" />

然后你告诉CF将该变量放入var范围。

为了使事情复杂化,当你 使用var scope时,你可能会遇到问题(当你不期望它们时变量值会发生变化)你的内联UDF。

因此,经验法则始终是,始终,始终, 始终 变量范围您的函数内部变量(包括查询名称)。有一个名为varScoper的工具可以帮助您找到需要变量范围的变量。最后我检查它并不完美,但它绝对是一个开始。

然而,在CFC中引用(显示/使用)没有范围的变量(显然不包括var-scoped变量,因为你不能指定要读取的范围)是一个错误的想法甚至在您的标准CFM页面上。从CF7开始,当您在未指定范围的情况下读取变量时,有9个范围以特定顺序进行检查,首先匹配获胜。使用CF8,该列表中可能有更多范围,我没有检查过。执行此操作时,如果您希望从另一个范围获取值,则存在从另一个范围获取值的风险;这是调试的噩梦......我向你保证。 ;)

简而言之:暗示变量的范围(在集合上)并不是一个糟糕的主意(尽管我通常会指定它);但推断变量的范围(在读取时)是在寻找麻烦。

答案 4 :(得分:2)

在变量范围中没有明确确定范围可能有效,但这不是一个好主意,老实说,的唯一原因是懒惰的IMO。如果你明确地确定了所有内容的范围1)你避免了潜在的问题,2)它使代码更容易阅读,因为毫无疑问,在哪些范围内。

对我而言,它并不会使代码更加冗长(当然也不会毫不必要地冗长) - 它实际上更容易阅读,避免混淆,并避免在没有明确范围的情况下可能出现的奇怪副作用。 / p>

答案 5 :(得分:1)

您问题的简单答案是: “不,没有必要”

但是,我认为最佳实践会建议您在访问这些变量时使用变量标识符。在我看来,任何未来遇到你的代码,并且正在寻找函数中间的人,都会立即知道变量的范围,而不必扫描函数顶部的局部函数。

事实上,我通过创建一个本地结构为我的CFC UDF增加了一些额外的冗长:

&lt; cfset var local = structNew()/&gt;

然后我将所有本地变量放在该结构中并以这种方式引用它们,所以我的代码看起来像这样:

&lt; cfset local.foo = variables.bar + 10 /&gt;

答案 6 :(得分:0)

在阅读完答案之后,我在想:

是的,这是安全的。通常,明确指定变量范围没有必要或有用。它只是增加了一种已经冗长的语言的混乱。

当然,正如Soldarnal指出的那样,有一个小的例外,需要限定变量范围的变量。也就是说,如果你有一个具有相同名称的函数局部变量。 (但你可能不应该这样做。)

答案 7 :(得分:0)

除了最佳实践之外,我相信它还可能取决于您访问cfc的方式我在创建对象和从coldfusion访问它们时没有遇到任何问题。但是我认为在通过flex / flash中的actionscript远程访问和/或映射它们时可能需要它。

答案 8 :(得分:0)

这是雷蒙德·卡姆登的一个非常好的CFC scope reference。 就个人而言,我更喜欢制作一个“自我”哈希来避免所有混淆(注意我没有在函数中使用'变量'范围):

<cfcomponent>
  <cfset variables.self = structNew()>
  <cfscript>
    structInsert(variables.self, <key>, <value>);
    ...
  </cfscript>

  <cffunction name="foo">
    self.<key> = <value>
    <cfreturn self.<key> />
  </cffunction>

  ...