PHP的相等性(==双等号)和恒等性(===三等号)比较运算符有何不同?

577

==

===

之间有什么区别?
  • 宽松比较 == 是如何工作的?
  • 严格比较 === 是如何工作的?

有哪些有用的例子?


@BenAubin,说真的,你所做的修改并没有任何改进。 - klutt
@BenAubin 我知道你想要帮忙,这是好的,但那些编辑并没有真正改善东西。现在你已经有了足够的声望,你的编辑将不会进入审核队列,所以请小心处理你的编辑。 - klutt
@klutt 我的编辑是有意的。原帖发布几分钟后,OP进行了一次编辑,要求提供Javascript和PHP两种语言的答案,因此许多回答都涉及这两种语言。正如我在编辑说明中提到的那样,我的编辑恢复了这个原始上下文。 - Ben Aubin
13个回答

706

=====的区别

宽松等于操作符==和严格全等操作符===的区别在官方文档中有详细解释:

比较运算符

示例 名称 结果
$a == $b 相等 如果执行类型强制转换后 $a 等于 $b,则返回TRUE。
$a === $b 全等 如果 $a 等于 $b 并且它们的类型相同,则返回 TRUE。

宽松==等于比较

如果你使用==操作符或其他使用宽松比较的操作符,例如!=<>==,则需要始终查看上下文来确定何时会进行类型转换以及转换规则,才能理解运算的实际含义。

类型转换规则

类型比较表格

作为参考和示例,你可以在官方文档中查看类型比较表格:

TRUE FALSE 1 0 -1 "1" "0" "-1" NULL array() "php" ""
TRUE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
FALSE FALSE TRUE FALSE TRUE FALSE FALSE TRUE FALSE TRUE TRUE FALSE TRUE
1 FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
0 FALSE FALSE FALSE TRUE FALSE FALSE TRUE FALSE TRUE TRUE FALSE TRUE
-1 FALSE FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
"1" FALSE FALSE FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE
"0" FALSE FALSE FALSE FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE
"-1" FALSE FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
NULL FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE TRUE FALSE FALSE
array() FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE TRUE FALSE FALSE
"php" FALSE FALSE FALSE TRUE FALSE FALSE如果您使用 === 操作符或任何其他使用严格比较的比较操作符,如 !=====,则始终可以确保类型不会 神奇地 更改,因为没有进行转换。因此,在使用严格比较时,类型和值必须相同,而不仅是值。

类型比较表

作为参考和示例,您可以在手册中查看比较表:

=== 的严格比较:

TRUE FALSE 1 0 -1 "1" "0" "-1" NULL array() "php" ""
TRUE
FALSE
1
0
-1
"1"
"0"
"-1"
NULL
array()

编辑注 - 此前已经正确引用,但将其转换为Markdown表格可读性更好。这不是剽窃。


73
还有其他人觉得 "000" == "0000" 很奇怪吗? - nickf
39
让我惊讶的是,false == array()和false == 0,但array() != 0,所以false == array() !=/== 0?这对我来说感觉很奇怪。 - Pim Jager
4
继续看下去:从这个角度来看,将一个值转换为BOOL类型,该值只需要落在“true”或“false”两个方面中的任何一个方面即可。这很容易进行类型转换。但是对于所有其他值而言,在所有实际目的上,它们具有几乎无限的组合方式。例如:"five" == 5吗?array(0) == 0吗?array(0,0,0) == 0吗?0.0000000000000000000000000000000000000000000000000001 == array()吗? - deceze
13
@Raithlin,小心数组。在JavaScript中,三个等号对于不同的数组会返回false,但只要它们的值相等,在PHP中会返回true - Pacerier
14
@Raithlin,还有很多要注意的地方。在JavaScript中: "000" != "00", "000" == null, "000" == false, "0x0" == false, array() == 0, false != null, array() != null, false == "0x0", false == "000". 而在PHP中,情况则相反: "000" == "00", "000" != null, "000" != false, "0x0" != false, array() != 0, false == null, array() == null, false != "0x0", false != "000" - Pacerier
显示剩余7条评论

252

如果两个不同的类型进行比较,操作符“==”会进行强制类型转换,而操作符“===”则执行“类型安全比较”。这意味着只有当两个操作数具有相同的类型和相同的值时,它才会返回true。

示例:

1 === 1: true
1 == 1: true
1 === "1": false // 1 is an integer, "1" is a string
1 == "1": true // "1" gets casted to an integer, which is 1
"foo" === "foo": true // both operands are strings and have the same value

警告:具有相同成员的两个实例属于同一个类,但却无法匹配===运算符。例如:

$a = new stdClass();
$a->foo = "bar";
$b = clone $a;
var_dump($a === $b); // bool(false)

3
Nitpick: === 只有在两个操作数类型相同且值相等时才会返回 true =) - gnud
1
@gnud 这正是他在示例中展示的。如果只是比较类型,它就会被称为“类型比较”,不是吗? - Rob Stevenson-Leggett
3
使用 PHP 已经有 8 年了,但昨天是我第一次陷入本应该使用 === 的情况。 - uuɐɯǝʃǝs
4
如果它们相等并且类型相同,则返回true。 如果它们相等,则返回true。 如果它们不相等,则返回true。 如果它们不相等,或者相等但类型不同,则返回true。 - Jeremy C
1
此外,使用 === 比 == 稍微更快,因为它在检查相等性之前不需要转换值。 - clauziere
显示剩余3条评论

121

一图胜千言:

PHP 双等号 == 等值运算符表格:

图片描述

PHP 三等号 === 全等运算符表格:

图片描述

创建这些图像的源代码:

https://github.com/sentientmachine/php_equality_charts

大师冥想

那些希望保持清醒的人,不要再往下读了,因为这一切都没有任何意义,除了说这就是 PHP 疯狂的分形设计。

  1. NAN != NAN 但是 NAN == true

  2. == 如果左边是数字,它会将左右操作数转换为数字,所以 123 == "123foo",但是 "123" != "123foo"

  3. 用引号括起来的十六进制字符串有时会被意外强制转换为浮点数,导致运行时错误。

  4. == 不是传递性的,因为 "0" == 00 == "" 但是 "0" != ""

  5. PHP 中尚未声明的变量为false,即使 PHP 有一种表示未定义的变量的方法,该特性在使用 == 时被禁用。

  • "6" == " 6""4.2" == "4.20""133" == "0133",但是133 != 0133。但是"0x10" == "16""1e3" == "1000"表明意外的八进制字符串转换会在没有指示或同意的情况下发生,从而导致运行时错误。

  • False == 0""[]"0"

  • 如果你给一个数字加1后它们已经达到了最大值,它们不会绕回,而是被强制转换为infinity

  • 一个新的类等于1。

  • False是最危险的值,因为False等于大多数其他变量,这大多数情况下会使其失去作用。

  • 希望:

    如果您使用PHP,请不要使用双等号运算符,因为如果您使用三个等号,唯一需要担心的是NAN和接近其数据类型的最大值的数字,因为它们将被强制转换为无穷。使用双等号时,任何东西都可以意外地==为任何其他内容,或者会在未经同意的情况下令人惊讶地进行强制转换,并!=到一个明显应该相等的内容。

    在PHP中任何使用==的地方都是糟糕的代码味道,因为根据隐式转换规则,它暴露了85个错误,这些规则似乎是由数百万程序员通过布朗运动编程设计的。


    1
    始终使用三个等号真的是一个好主意(也安全)吗? - Chazy Chaz
    3
    是的,使用三个等号的传递性质可以使其更加安全和适用于大规模网络。 - Eric Leschinski
    1
    一个数字如何接近无穷大?[爆炸脑图] - Tim
    2
    特别需要注意的是 1.0 !== 1,这可能会让人有些困惑,例如 floor(4 / 3) === 1 ? 'works as might be expected' : 'what?' - Jake
    1
    @EricLeschinski floor(4/3) === 1 不会被评估为真,因为 floor 返回一个 float(即使返回值必须是整数,但它不是按类型定义的)- 因此需要指出这个陷阱的原因。JavaScript 没有这个问题,因为它只有一种数字类型(尽管由于这个原因存在其他问题,如整数舍入)。 - Jake

    31
    关于JavaScript:
    ===运算符与==运算符的作用相同,但它要求其操作数不仅具有相同的值,而且还具有相同的数据类型。
    例如,下面的示例将显示“x和y相等”,但不会显示“x和y完全相同”。
    var x = 4;
    var y = '4';
    if (x == y) {
        alert('x and y are equal');
    }
    if (x === y) {
        alert('x and y are identical');
    }
    

    1
    @DavidThomas 这并不完全相同。请参见https://dev59.com/-2cs5IYBdhLWcg3wwmrA#12598484 - xdazz
    1
    我已经对这个答案进行了DV,因为它是在OP的自我回答详细说明了关于松散类型比较的相同见解之后的30分钟内发布的。这个针对最初和当前标记为php的问题的javascript答案真的应该被删除,但要这样做,需要通过社区努力来降低投票总数。换句话说,需要更多的DV才能进行适当的管理并删除这个(已删除用户的)答案。 - mickmackusa

    23

    关于对象比较的其他答案中还有一个补充:

    == 使用对象名称和它们的值来比较对象。如果两个对象是相同类型并且具有相同的成员值,则$a == $b将返回true。

    === 比较对象的内部对象ID。即使成员相等,如果它们不是完全相同的对象,则$a !== $b

    class TestClassA {
        public $a;
    }
    
    class TestClassB {
        public $a;
    }
    
    $a1 = new TestClassA();
    $a2 = new TestClassA();
    $b = new TestClassB();
    
    $a1->a = 10;
    $a2->a = 10;
    $b->a = 10;
    
    $a1 == $a1;
    $a1 == $a2;  // Same members
    $a1 != $b;   // Different classes
    
    $a1 === $a1;
    $a1 !== $a2; // Not the same object
    

    9
    这里涉及到数据类型。以BOOL(真或假)为例: true也等于1false也等于0 当使用==进行比较时,不考虑数据类型:
    如果你有一个变量是1(也可以是true),那么: $var=1; 然后使用==进行比较:
    if ($var == true)
    {
        echo"var is true";
    }
    

    但是$var实际上并不等于true,是吗?它的整数值为1,而这个值代表了true

    使用===时,会检查数据类型以确保两个变量/对象/任何内容使用相同的类型。

    所以如果我执行以下操作:

    if ($var === true)
    {
        echo "var is true";
    }
    

    如果条件为$var !== true,那么它只有在== true的情况下才会成立(如果你知道我的意思的话)。

    为什么需要这个呢?

    很简单——让我们来看一下PHP的一个函数:array_search()

    array_search()函数只是在数组中搜索一个值,并返回值所在元素的键。如果在数组中找不到该值,则返回false。但是,如果你在数组的第一个元素中进行array_search(),它将返回0,而0等于false。

    所以,如果你这样做:

    $arr = array("name");
    if (array_search("name", $arr) == false)
    {
        // This would return 0 (the key of the element the val was found
        // in), but because we're using ==, we'll think the function
        // actually returned false...when it didn't.
    }
    

    所以,现在你知道这可能是一个问题了吗?

    大多数人在检查函数是否返回false时不使用== false。相反,他们使用!。但事实上,这与使用== false完全相同,因此如果你这样做:

    $arr = array("name");
    if (!array_search("name", $arr)) // This is the same as doing (array_search("name", $arr) == false)
    

    对于这种情况,你应该使用===,以便检查数据类型。


    4

    PHP双等号 == :

    在大多数编程语言中,比较运算符(==)会检查变量的数据类型和内容是否相等。但是,在PHP中,标准的比较运算符(==)有所不同。它会尝试将两个变量转换为相同的数据类型,然后再检查这些变量的内容是否相同。得到以下结果:

    <?php
        var_dump( 1 == 1 );     // true
        var_dump( 1 == '1' );   // true
        var_dump( 1 == 2 );     // false
        var_dump( 1 == '2' );   // false
        var_dump( 1 == true );  // true
        var_dump( 1 == false ); // false
    ?>
    

    PHP 三等号 === :

    这个运算符还会检查变量的数据类型,仅在两个变量具有相同内容和相同数据类型时返回(bool)true。因此,以下操作将是正确的:

    <?php
        var_dump( 1 === 1 );     // true
        var_dump( 1 === '1' );   // false
        var_dump( 1 === 2 );     // false
        var_dump( 1 === '2' );   // false
        var_dump( 1 === true );  // false
        var_dump( 1 === false ); // false
    ?>
    

    阅读PHP中"=="和"==="的区别是什么


    2
    您需要使用 === 来测试函数或变量是否为 false,而不仅仅是等于 false(零或空字符串)。
    $needle = 'a';
    $haystack = 'abc';
    $pos = strpos($haystack, $needle);
    if ($pos === false) {
        echo $needle . ' was not found in ' . $haystack;
    } else {
        echo $needle . ' was found in ' . $haystack . ' at location ' . $pos;
    }
    

    在这种情况下,strpos会返回0,而在测试中这将等同于false。
    if ($pos == false)
    

    或者

    if (!$pos)
    

    这并不是您想要的内容。

    2
    到目前为止,所有的答案都忽略了 === 存在的一个危险问题。虽然已经有人提到过,但并没有强调,整数和双精度浮点数是不同的类型,所以以下代码可能会出现问题:
    ```javascript if (x === 0.1) { // do something } ```

    $n = 1000;
    $d = $n + 0.0e0;
    echo '<br/>'. ( ($n ==  $d)?'equal' :'not equal' );
    echo '<br/>'. ( ($n === $d)?'equal' :'not equal' );
    

    给予:
     equal
     not equal
    

    请注意,这不是“舍入误差”的情况。这两个数字在最后一位上完全相等,但它们具有不同的类型。
    这是一个恶劣的问题,因为如果所有数字都足够小(“足够小”取决于您运行的硬件和操作系统),则使用===的程序可以愉快地运行多年。然而,如果偶然发生的情况下,整数足够大以至于可以转换为双精度浮点数,则其类型将被永久更改,即使随后的操作或许多操作可能会将其带回到小整数值。而且,情况变得更糟。它可以传播-双重性感染可以一次一个计算地传递给它所接触的任何东西。
    在现实世界中,这很可能是处理2038年之后的日期的程序存在的问题。此时,UNIX时间戳(自1970-01-01 00:00:00 UTC以来的秒数)将需要超过32位,因此它们的表示将在某些系统上“神奇地”切换为双精度浮点数。因此,如果计算两个时间之间的差异,您可能会得到几秒钟,但作为双精度浮点数,而不是2017年的整数结果。
    我认为这比字符串和数字之间的转换要糟糕得多,因为它很微妙。我发现很容易跟踪哪个是字符串,哪个是数字,但跟踪数字中的位数超出了我的能力。
    因此,在上面的答案中,有一些不错的表格,但没有区分1(作为整数)、1(微妙的双精度)和1.0(明显的双精度)。此外,建议始终使用===而不是==并不好,因为===有时会失败,而==可以正常工作。此外,JavaScript在这方面不等同,因为它只有一个数字类型(内部可能有不同的比特表示,但对于===不会造成问题)。
    我的建议-两者都不用。您需要编写自己的比较函数才能真正解决这个问题。

    1

    “==”(等于)与“===”(全等于)的区别

    PHP提供了两个比较运算符来检查两个值是否相等。它们之间的主要区别在于,'=='检查两个操作数的值是相等或不相等. 另一方面,'==='检查操作数的值和类型是相等或不相等

    == (等于)

    === (全等于)

    示例 =>

    <?php 
        $val1 = 1234;
        $val2 = "1234";
        var_dump($val1 == $val2);// output => bool(true)
        //It checks only operands value
    ?> 
    
    
    <?php 
        $val1 = 1234;
        $val2 = "1234";
        var_dump($val1 === $val2);// output => bool(false)
        //First it checks type then operands value
    ?> 
    

    如果我们将 $val2 强制转换为 (int)$val2 或 (string)$val1,则返回 true。
       <?php 
            $val1 = 1234;
            $val2 = "1234";
            var_dump($val1 === (int)$val2);// output => bool(true)
            //First it checks type then operands value
        ?> 
    

    或者

      <?php 
            $val1 = 1234;
            $val2 = "1234";
            var_dump($val1 === (int)$val2);// output => bool(true)
            //First it checks type then operands value
        ?> 
    

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