PHP中的is_null($x)和$x === null有什么区别?

166

可能是重复问题:
is_null($var)和($var === null)有什么区别?

PHP有两个(我知道的),如果计算isset(),则有三个方法来确定值是否为null:is_null()=== null。我听说过,但尚未证实,=== null更快,但在代码审查中,有人强烈建议我改用is_null(),因为它专门设计用于null评估目的。他还开始谈论数学或其他内容。

无论如何,is_null()显然较慢的事实也使我相信它正在做比=== null更多的工作,并且可能更受欢迎。有没有使用其中一个的理由?总是有一个首选项吗?isset()呢?

作为可能不会关闭此问题的补充,isset()is_null()的区别是什么?它似乎只会抑制通知,因此除非您实际上希望获得未定义变量的通知,否则使用is_null()的任何原因?如果您知道变量在初始化时,则怎么样?

最后,是否有任何数学原因优先使用is_null()而不是=== null?关于null无法比较的某些内容?


2
好问题,但据我所学,这种“改进”是如此微小,以至于你写的方式并不重要。无论如何,我还在等待有能力的人来回答这个问题,我也想知道。 - OptimusCrime
2
投票支持重新开放的人应该指出为什么这个问题不是与之关闭的重复问题,或者为什么它应该被允许共存。同时请考虑标记以进行合并。 - Gordon
3
性能方面:PHP 7 改变了旧有的智慧:=== 不再比 is_null 更快。 - Gogowitsch
7个回答

231

is_null=== null在功能上完全没有区别。

唯一的区别在于is_null是一个函数,因此:

  1. 稍微慢一点(函数调用开销);
  2. 可以用作回调,例如array_map('is_null', $array)

个人而言,只要可能就使用null ===,因为它更符合false ===true ===检查的一致性。

如果你想,可以检查代码:is_identical_function===)和php_is_typeis_null)对于IS_NULL情况做同样的事情。


相关的语言结构isset()在进行null检查之前检查变量是否实际存在。因此,isset($undefinedVar)不会抛出警告。

还要注意,isset()有时可能会返回true,即使值为null——这是在使用重载对象时的情况,即如果对象定义了一个返回trueoffsetExists/__isset方法,即使偏移量为null(这实际上相当普遍,因为人们在offsetExists/__isset中使用array_key_exists)。


速度差异方面的观点很好。 - Robert
13
根据文档中的评论,is_null() 在 PHP7 中比 === NULL 稍微快一点,但两者之间的差距比以前版本要小得多,不值得担心。 - Martin James
1
我已经在 PHP 7.4 上使用 for 循环进行了 1 亿次迭代的测试。两者之间的差异微不足道。只需选择一个并使用即可。 - Flame
1
使用 === nullis_null() 进行空值检查的唯一真正区别是上面提到的回调函数。因为存在 is_null(),所以每次想要使用 null 检查来进行 array_filter() 等操作时,你不必创建一个闭包/匿名函数并在其中放置 === null,而只需将 'is_null' 作为回调函数传入即可。它的存在是为了使代码更易读,而不是为了增加执行速度。 - Adrian Wiik

19

正如其他人所述,使用===is_null()之间存在时间差异。我进行了一些快速测试并得到了以下结果:

<?php

//checking with ===
$a = array();
$time = microtime(true);
for($i=0;$i<10000;$i++) {
    if($a[$i] === null) {
         //do nothing
    }
}
echo 'Testing with === ', microtime(true) - $time, "\n";

//checking with is_null()
$time = microtime(true);
for($i=0;$i<10000;$i++) {
    if(is_null($a[$i])) {
         //do nothing
    }
}
echo 'Testing with is_null() ', microtime(true) - $time;
?>

提供结果

使用 === 进行测试得到 0.0090668201446533

使用 is_null() 进行测试得到 0.013684034347534

查看代码演示


46
在一个循环里执行了10000个操作,时间差不到5毫秒。这没关系,它永远都不会有关系。没有人试图提高应用程序性能时会想:“该死的,如果我能在这个空值检查中节省半微秒!”也永远不会有这样的人。 - Mark Amery
18
我会尽力进行翻译,并保证在不改变原意的基础上使其更易于理解。以下是需要翻译的内容:“@MarkAmery 我会选择在同等成本下性能更好的选项,而且我总是这样做。在一个包含50,000个以上文件的应用程序中,不够关注比更加关注更糟糕。” - Aleksandr Makov
12
我认为这里的重点是,如果你已经使用了“is_null”,就没有必要进行重构,但是从现在开始使用它则没有意义,如果你明白我的意思的话。 - PaulSkinner
1
有些情况下,简单的操作会被重复很多次。例如,一个解析器需要查看长文件中的每个字符。 - donquixote
3
程序执行时间往往服从帕累托分布,即代码库的大约20%负责了大约80%的运行时间(当它不是10/90甚至1/99时)。因此,这种微小的优化通常不会带来太大的收益。 - Marcel Hernandez
显示剩余2条评论

6

它们都有各自的用处,但只有isset()函数可以避免未定义变量的警告:

$ php -a
Interactive shell

php > var_dump(is_null($a));
PHP Notice:  Undefined variable: a in php shell code on line 1
bool(true)
php > var_dump($a === null);
PHP Notice:  Undefined variable: a in php shell code on line 1
bool(true)
php > var_dump(isset($a));
bool(false)
php >

6

我无法确定使用 is_null 还是 === null 更好。但在数组上使用 isset 时请注意。

$a = array('foo' => null);

var_dump(isset($a['foo'])); // false
var_dump(is_null($a['foo'])); // true
var_dump(array_key_exists('foo', $a)); // true

+1 for array_key_exists('foo', $a)。使用它可以查找设置为null的键,因为由于某种原因is_null($a['foo'])对于未定义的属性和空键都返回true??? - Necro
“Beware”是什么意思?isset(nullValue)将始终返回false - Brad Kent
我不记得为什么我特别写了那个,因为那是很久以前的事了。我猜想当时我认为使用isset检查数组键是否存在是一种常见做法。但在这种情况下最好使用array_key_exists,但我已经有10年没有再使用PHP了 :) - mAu

5

===is_null是一样的。

根据这个评论is_null只比===慢250ns。我认为这是因为函数比操作符慢。


在PHP 7.2.19(和i5-8265U)上,is_null实际上更快。但是null ===只比它慢1纳秒。不要担心差异。 - Henk Poley
参考资料,约1纳秒在3.9GHz下大约是4到5个时钟周期。鉴于威士忌湖似乎能够每个周期处理6条指令,这仍然可以达到24到28条指令。但这远远超出了PHP底层硬件的细节(它通常比C慢> 10x-30x)。 - Henk Poley

4

如果变量可能未定义,则需要使用isset()。当变量未定义或=== null时,它返回false(是的,它很丑)。只有isset()empty()不会引发E_NOTICE,如果变量或数组元素不存在。

is_null=== null之间实际上没有区别。我认为===更好,但是当您需要出于某种可疑的原因使用call_user_func时,您必须使用is_null


2

PHP文档对于is_null, === null, isset进行了深入的探讨和实验。特别是要仔细阅读评论部分。


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