PowerShell 嵌套函数中的变量作用域

Variable Scopes Within PowerShell Nested Functions

我从一家 major/reputable 公司获得了这个广泛的 PowerShell 脚本,它应该可以完美地工作。好吧,它没有。
该脚本由许多嵌套函数组成,其中许多变量传递给主 parent 函数,然后传递给它的所有 children。 Children 谁使用和修改了所有这些变量。

为什么所有这些变量都不包含正确的数据?
这是我正在谈论的结构:

f1 {
     f2 {
          v #prints 0
          v = 1
          f3
     }
     f3 {
          v #prints 1
          v = 2
     }
     v = 0
     f2
     v #should print 2 but prints 0
}

注:

这是使用 PowerShell 3.0 和 4.0 测试的。

在嵌套函数中,所有子函数都可以访问父函数的所有变量。对变量的任何更改在当前函数的局部范围内以及之后调用的所有嵌套子函数中都是可见的。当子函数执行完成后,变量将return恢复为子函数调用前的原始值。

为了在所有嵌套函数范围内应用变量更改,需要将变量范围类型更改为 AllScope:

Set-Variable -Name varName -Option AllScope

这样,无论变量在嵌套函数的哪个级别被修改,即使在子函数终止后更改仍然存在并且父函数将看到新的更新值。


嵌套函数中变量作用域的正常行为:

function f1 ($f1v1 , $f1v2 )
{
        function f2 ()
       {
               $f2v = 2
               $f1v1 = $f2v #local modification visible within this scope and to all its children
               f3
               "f2 -> f1v2 -- " + $f1v2 #f3's change is not visible here
       }
        function f3 ()
       {
               "f3 -> f1v1 -- " + $f1v1 #value reflects the change from f2
               $f3v = 3
               $f1v2 = $f3v #local assignment will not be visible to f2
               "f3 -> f1v2 -- " + $f1v2
       }
       
        f2
        "f1 -> f1v1 -- " + $f1v1 #the changes from f2 are not visible
        "f1 -> f1v2 -- " + $f1v2 #the changes from f3 are not visible
}

f1 1 0

打印输出:

f3 -> f1v1 -- 2
f3 -> f1v2 -- 3
f2 -> f1v2 -- 0
f1 -> f1v1 -- 1
f1 -> f1v2 -- 0

具有 AllScope 个变量的嵌套函数:

function f1($f1v1, $f1v2)
{
    Set-Variable -Name f1v1,f1v2 -Option AllScope
    function f2()
    {
        $f2v = 2
        $f1v1 = $f2v #modification visible throughout all nested functions
        f3
        "f2 -> f1v2 -- " + $f1v2 #f3's change is visible here
    }
    function f3()
    {
        "f3 -> f1v1 -- " + $f1v1 #value reflects the change from f2
        $f3v = 3
        $f1v2 = $f3v #assignment visible throughout all nested functions
        "f3 -> f1v2 -- " + $f1v2 
    }
    
    f2
    "f1 -> f1v1 -- " + $f1v1 #reflects the changes from f2 
    "f1 -> f1v2 -- " + $f1v2 #reflects the changes from f3 
}

f1 1 0

打印输出:

f3 -> f1v1 -- 2
f3 -> f1v2 -- 3
f2 -> f1v2 -- 3
f1 -> f1v1 -- 2
f1 -> f1v2 -- 3