在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>
答案 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>
...