Области Переменных Внутри Вложенных Функций PowerShell


Мне дали этот обширный сценарий PowerShell от крупной/авторитетной корпорации, который должен был работать безупречно. Ну, это не так.
Скрипт состоит из множества вложенных функций с множеством переменных, передаваемых в основную родительскую функцию, а затем во все ее дочерние функции. Дети, которые используют и изменяют все эти переменные.

Почему все эти переменные не содержат правильных данных?
Вот структура, о которой я говорю:

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

1 ответ:

Внутри вложенных функций все дочерние функции имеют доступ ко всем переменным родительских функций. Любые изменения переменных видны в локальной области текущей функции и всех вложенных дочерних функций, вызываемых впоследствии. Когда дочерняя функция завершит выполнение, переменные вернутся к исходным значениям до вызова дочерней функции.

Чтобы применить изменения переменной во всех областях вложенных функций, область действия переменной тип должен быть изменен на 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