变量的作用域和变量

4

If I have a function like

<cfscript>
function say(what) {
  var a = what;
  variables.b = what;
  return what;
}
</cfscript>

我认为变量 a 的作用域是 variables,但是转储 variables 只返回了 b。那么变量 a 的作用域是什么?


4
我相信变量a在本地作用域内,它应该只存在于函数内部。 - Evik James
3
当你使用var时,变量的作用域限制在函数内部,与使用local.a相同。 - Bernhard Döbler
5个回答

4

这其实是一条注释,但太长了。看下面的代码:

<cfscript>
function doMath() {
   var a = 1;
   local.b = 2;
   return a + local.b;
   }
</cfscript>

乍一看,人们可能会认为 var local. 具有相同的范围。毕竟它们都仅存在于函数内部。当函数完成时,这两个变量都不存在了。结束了吗?也许不是。

在ColdFusion中,我们有暗示范围和隐式范围。

url.a
form.a
cookie.a
session.a
application.a
local.a
arguments.a
myQuery.a

所有变量都不同。如果我有以上所有有效变量,并且我说<cfoutput>#a#</cfoutput>,我将得到哪个a?ColdFusion会浏览其暗示范围列表,直到找到匹配项为止。并显示该内容。所以回到问题上来。

因此,当我在函数内部时,如果使用var,我是在告诉ColdFusion,查看所有的暗示范围,直到找到匹配项为止。如果我使用local.a,我是在告诉ColdFusion只查看一个地方并使用它。

好处

我知道我正在选择哪个变量。如果您正在编写需要尽可能快的代码,您将不使用暗示范围。如果您正在编写最易读的代码,您也将不使用暗示范围。

因此,var不等同于local.


2
我知道不包括作用域可能会更易读和减少打字,但在追踪一些奇怪的作用域问题后,我完全支持在我的意图上非常明确。 :-) - Shawn
另请参见:https://dev59.com/Q33aa4cB1Zd3GeqPdXMJ#22314824 - James A Mohler

4

了解作用域可以帮助您避免一些极其难以追踪的问题。在大多数情况下,var aa 放入本地作用域,并且可以作为本地变量引用。如果之后声明该变量,它将覆盖已经存在于本地作用域中的任何 a 变量。

https://trycf.com/gist/faf04daa53194a5fad2e69e164518299/acf2016?theme=monokai

<cfscript>
function say() {
    local.a = "local" ; 
    var b   = "var" ;

    lv = local.b ; // We didn't explicitly assign b to Local scope. 

    try {
        v = variables ; // Let's dump the variables scope. 
    } catch (any e) {
        v = "Error: " & e.message ;
    }

    variables.nh = "Now here." ; // Explicitly populate variables scope.

    var c = "var c" ; // We have a variables scope, what happens to var?

    try {
        v2 = variables ; // Let's dump the variables scope. 
    } catch (any e) {
        v2 = "Error: " & e.message ;
    }

    var d = "var" ;
    local.d = "local" ;

    local.e = "local" ;
    var e = "var" ;

    return {
        a  : a ,       // Local.
        b  : b ,       // Var.
        d  : d ,       // Which one?
        e  : e ,       // Which one?
        el : local.e , // Which one?? 
        l  : lv ,      // Ref b in local scope.
        l2 : local ,   // Dump local scope.
        v  : v ,       // There doesn't seem to be a variables scope yet.
        v2 : v2        // Defined a variable scope and now here.
    } ;
}

writeDump(say());
</cfscript>

Output 1

我们可以看到,声明var bb放入local作用域中,只有在我们向其中声明了一些内容后,variables作用域才存在。我们可以引用local.b,但variables.b不存在。在我们明确创建并填充了nhvariables作用域之后,我们创建了一个var c。这也没有进入variables作用域,而是进入了local作用域。

当一个变量在localvar中被使用相同的名称声明时,最后一个声明的变量将覆盖另一个变量(参见deel)。要注意这点。

还要注意函数中的空arguments作用域也在local作用域中。

关于作用域的观察,我的最后两个需要注意的事项如下:

https://trycf.com/gist/65b73e7a57d0434049d0eb9c0d5f9687/acf11?theme=monokai

<cfscript>
function ks() {
    variables.jay   = "Snoogins." ; // variables scope leaks out of function.
    local.silentbob = "____" ;      // local scope stays inside function.
}

function sayArgs(arg) {
    local.arg = "local" ; // Order after agruments in CF10 but not 2016.

    ks() ; // Run ks() function to instantiate jay and silentbob.

    return {
        arg    : arg ,       // CF10 = arguments scope. CF11+ = local scope.
        args   : arguments ,
        local  : local ,     // No leakage from ks().
        vars   : variables   // Jay leaks from ks().
    } ;
}

writeDump(sayArgs("argue")) ;
</cfscript>

Output 2

我注意到两件事情:

首先,在CF10和后来的CF版本中,argumentslocal作用域的评估顺序有所不同。当前CF2016(或2011+)的行为是函数内部的local作用域不会覆盖arguments作用域,但它将首先进行评估。在CF10中相反:arguments会首先进行评估。Lucee和Railo的行为类似于ACF2016。

第二个注意点与变量泄漏有关,涉及variableslocallocal只存在于声明它的函数内部。 variables更加全局,可以在函数外部访问。

https://helpx.adobe.com/coldfusion/developing-applications/the-cfml-programming-language/using-coldfusion-variables/about-scopes.html << 对于ACF2016,显示了使用local覆盖arguments的评估顺序。

http://www.learncfinaweek.com/week1/Scopes/ << 列出了ACF10评估顺序,但在后续版本中,argumentslocal的顺序被交换。

https://help.adobe.com/zh_CN/ColdFusion/9.0/Developing/WSc3ff6d0ea77859461172e0811cbec09af4-7fdf.html << 这是 ACF9 的文档。它列出了与 ACF2016 相同的顺序,但在 ACF10 中不同。我现在没有 CF9 的副本来测试,因此我不知道 CF9 和更早版本如何处理评估。


3

让我们逐行解释(看注释):

<cfscript>
function say(what) {

    // using the "var" keyword define a variable named "a" in the "local" scope
    // the "local" scope is private to the current function context
    // give to "a" the value of the "what" argument
  var a = what;


    // explicitly define a variable "b" in the "variables" scope 
    // the "variables" scope is available anywhere in the current template context
    // give to "b" the value of the "what" argument
  variables.b = what;


    // return the value of "what" argument
  return what;
}
</cfscript>

var是一个关键字
variables是一个作用域
local是一个私有作用域(也是一个关键字)

local作用域可以通过var a = "foo"local.a = "foo"来填充。


3
使用var关键字声明变量将其放入局部作用域中,而不是变量作用域中。

0
在当前的例子中,变量a仅在函数范围内可用。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接