Joh*_*ees 2 powershell closures scriptblock
以下PowerShell代码显示从闭包调用的函数的意外作用域行为.你能解释一下这是"按设计"还是缺陷?
function runblock($block) {
$x = 4
& $block
}
function printx() {
" in printx: x=" + $x
}
"PSVersion $($PSVersionTable.PSVersion)"
$x = 1
$b = {"In block x=" + $x ; $x = 3 ; printx}
$x = 2
runblock $b
$x = 1
$b = {"In closure x=" + $x ; $x = 3 ; printx}.GetNewClosure()
$x = 2
runblock $b
Run Code Online (Sandbox Code Playgroud)
以上输出是
PSVersion 3.0
In block x=4
in printx: x=3
In closure x=1
in printx: x=4
Run Code Online (Sandbox Code Playgroud)
大部分输出对我有意义:
脚本块输出,In block x=4因为其父作用域是runblock函数.该printx函数输出x=3自它的父范围是脚本块范围.
闭包输出In closure x=1因为$x通过GetNewClosure调用捕获的值.一切如预期.
但是:printx关闭输出的调用in printx: x=4.因此,在其中printx执行的范围不受闭包范围的影响$x = 3.
对我来说,从普通脚本块调用的函数确实可以看到脚本块作用域中的变量,但是从闭包中调用的函数看不到闭包中的变量.
考虑以下代码:
function Run {
param($ScriptBlock)
$a = 3
# Picture 4
& $ScriptBlock
}
function Print {
# Picture 6
"Print `$a=$a"
"Print `$b=$b"
}
$a = 1
$b = 1
# Picture 1
$SB = {
# Picture 5
"Closure `$a=$a"
"Closure `$b=$b"
Print
}.GetNewClosure()
# Picture 2
$a = 2
$b = 2
# Picture 3
Run $SB
Run Code Online (Sandbox Code Playgroud)
它打印:
Closure $a=1
Closure $b=1
Print $a=3
Print $b=2
Run Code Online (Sandbox Code Playgroud)
图1:从全局范围开始,您可以在其中定义一些变量.

图2: GetNewClosure()创建新模块并将变量复制到它.(红色箭头显示父范围关系)

图3:你改变了变量的值.模块范围不受影响.

图4:Run调用的函数.它创建局部变量$a.(蓝色箭头显示呼叫方向)

图5: $SB调用脚本块.脚本块绑定到模块会话状态,因此您转移到它.

图6:Print调用的函数.函数绑定到全局会话状态,因此返回到它.
| 归档时间: |
|
| 查看次数: |
508 次 |
| 最近记录: |