PHP - 'use()' 或 'global' 在闭包中访问全局变量的区别?
PHP - Difference between 'use()' or 'global' to access a global variable in a closure?
以下两种在闭包中访问全局变量的情况在性能或其他方面是否存在差异:
案例一:
$closure = function() use ($global_variable) {
// Use $global_variable to do something.
}
案例二:
$closure = function() {
global $global_variable;
// Use $global_variable to do something.
}
Use
关键字在父范围内,而global
和$GLOBALS
来自任何地方。
这意味着,如果您使用 global
,您可能不知道值是否发生了变化,从哪里发生了什么变化,变化的种类是什么。
您可以使用 use
进行更多控制。所以这取决于你的需求。
你的两个例子有一个重要的区别:
$global_variable = 1;
$closure = function() use ($global_variable) {
return $global_variable;
};
$closure2 = function() {
global $global_variable;
return $global_variable;
};
$global_variable = 99;
echo $closure(); // this will show 1
echo $closure2(); // this will show 99
use
在闭包定义期间采用 $global_variable
的值,而 global
在执行期间采用 $global_variable
的当前值。
global
从全局范围继承变量,而 use
从父范围继承它们。
你的标题问题已经回答得很好,所以我会跳过它。
虽然您在 body 中提出了不同的问题。哪个性能更好?
我做了一个简单的测试,我在 PHP Sandbox:
<?php
$bool = true;
$one = function() use ($bool) {
return $bool;
};
$two = function() {
global $bool;
return $bool;
};
for ($power = 1; $power <= 10000000; $power *= 10) {
echo "loops = {$power}\n";
$before = microtime(true);
for ($i=0 ; $i<20000 ; $i++)
$one();
$after = microtime(true);
$timeOne = ($after-$before)/$i;
echo "{$timeOne} sec/one\n";
$before = microtime(true);
for ($i=0 ; $i<20000 ; $i++)
$two();
$after = microtime(true);
$timeTwo = ($after-$before)/$i;
echo "{$timeTwo} sec/two\n";
echo "Winner: " . ($timeOne > $timeTwo ? 'one' : 'two') . "\n\n";
}
而且结果非常不确定:
loops = 1
6.2644481658936E-8 sec/one
5.6242942810059E-8 sec/two
Winner: one
loops = 10
5.4049491882324E-8 sec/one
4.9102306365967E-8 sec/two
Winner: one
loops = 100
5.1343441009521E-8 sec/one
5.4597854614258E-8 sec/two
Winner: two
loops = 1000
5.5849552154541E-8 sec/one
5.2559375762939E-8 sec/two
Winner: one
loops = 10000
5.6040287017822E-8 sec/one
5.3608417510986E-8 sec/two
Winner: one
loops = 100000
5.8901309967041E-8 sec/one
4.960298538208E-8 sec/two
Winner: one
loops = 1000000
6.2298774719238E-8 sec/one
6.9999694824219E-8 sec/two
Winner: two
loops = 10000000
8.3756446838379E-8 sec/one
5.9354305267334E-8 sec/two
Winner: one
也许 use
如果比 global
快一点,但您可能应该根据此决定使用哪个。这都是关于 use-case(没有双关语意)。
您可以使用 use
进行更多控制,即 parent-scoped,因此在大多数情况下这可能是您最好的选择,但如果您确实需要全局范围内的变量,答案显而易见。
另请注意,您只能将 use
与匿名 (lambda) 函数一起使用(就像在我的测试示例中一样)。如果你想在正常定义的函数中具有相同的功能,那么你需要将有问题的变量作为函数参数,但由指针引用。当心,这并非没有警告。如果您的函数对引用变量进行了任何更改,这些更改将不是函数的局部更改。这是一个例子。
// ...
function three(&$var) {
return $var;
}
以下两种在闭包中访问全局变量的情况在性能或其他方面是否存在差异:
案例一:
$closure = function() use ($global_variable) {
// Use $global_variable to do something.
}
案例二:
$closure = function() {
global $global_variable;
// Use $global_variable to do something.
}
Use
关键字在父范围内,而global
和$GLOBALS
来自任何地方。
这意味着,如果您使用 global
,您可能不知道值是否发生了变化,从哪里发生了什么变化,变化的种类是什么。
您可以使用 use
进行更多控制。所以这取决于你的需求。
你的两个例子有一个重要的区别:
$global_variable = 1;
$closure = function() use ($global_variable) {
return $global_variable;
};
$closure2 = function() {
global $global_variable;
return $global_variable;
};
$global_variable = 99;
echo $closure(); // this will show 1
echo $closure2(); // this will show 99
use
在闭包定义期间采用 $global_variable
的值,而 global
在执行期间采用 $global_variable
的当前值。
global
从全局范围继承变量,而 use
从父范围继承它们。
你的标题问题已经回答得很好,所以我会跳过它。
虽然您在 body 中提出了不同的问题。哪个性能更好?
我做了一个简单的测试,我在 PHP Sandbox:
<?php
$bool = true;
$one = function() use ($bool) {
return $bool;
};
$two = function() {
global $bool;
return $bool;
};
for ($power = 1; $power <= 10000000; $power *= 10) {
echo "loops = {$power}\n";
$before = microtime(true);
for ($i=0 ; $i<20000 ; $i++)
$one();
$after = microtime(true);
$timeOne = ($after-$before)/$i;
echo "{$timeOne} sec/one\n";
$before = microtime(true);
for ($i=0 ; $i<20000 ; $i++)
$two();
$after = microtime(true);
$timeTwo = ($after-$before)/$i;
echo "{$timeTwo} sec/two\n";
echo "Winner: " . ($timeOne > $timeTwo ? 'one' : 'two') . "\n\n";
}
而且结果非常不确定:
loops = 1
6.2644481658936E-8 sec/one
5.6242942810059E-8 sec/two
Winner: one
loops = 10
5.4049491882324E-8 sec/one
4.9102306365967E-8 sec/two
Winner: one
loops = 100
5.1343441009521E-8 sec/one
5.4597854614258E-8 sec/two
Winner: two
loops = 1000
5.5849552154541E-8 sec/one
5.2559375762939E-8 sec/two
Winner: one
loops = 10000
5.6040287017822E-8 sec/one
5.3608417510986E-8 sec/two
Winner: one
loops = 100000
5.8901309967041E-8 sec/one
4.960298538208E-8 sec/two
Winner: one
loops = 1000000
6.2298774719238E-8 sec/one
6.9999694824219E-8 sec/two
Winner: two
loops = 10000000
8.3756446838379E-8 sec/one
5.9354305267334E-8 sec/two
Winner: one
也许 use
如果比 global
快一点,但您可能应该根据此决定使用哪个。这都是关于 use-case(没有双关语意)。
您可以使用 use
进行更多控制,即 parent-scoped,因此在大多数情况下这可能是您最好的选择,但如果您确实需要全局范围内的变量,答案显而易见。
另请注意,您只能将 use
与匿名 (lambda) 函数一起使用(就像在我的测试示例中一样)。如果你想在正常定义的函数中具有相同的功能,那么你需要将有问题的变量作为函数参数,但由指针引用。当心,这并非没有警告。如果您的函数对引用变量进行了任何更改,这些更改将不是函数的局部更改。这是一个例子。
// ...
function three(&$var) {
return $var;
}