PHP等式(== double equals)和identity(=== triple equals)比较运算符有何不同?

How do the PHP equality (== double equals) and identity (=== triple equals) comparison operators differ?

=====有什么区别?

  • 松散的==比较究竟是如何工作的?
  • 严格的===比较究竟是如何工作的?

有哪些有用的例子?


=====的区别

本手册对松散==等号运算符与严格===等号运算符的区别作了详细说明:

Comparison Operators

1
2
3
4
5
6
┌──────────┬───────────┬───────────────────────────────────────────────────────────┐
│ Example  │ Name      │ Result                                                    │
├──────────┼───────────┼───────────────────────────────────────────────────────────┤
$a ==  $b │ Equal     │ TRUE if $a is equal to $b after type juggling.            │
$a === $b │ Identical │ TRUE if $a is equal to $b, and they are of the same type.
└──────────┴───────────┴───────────────────────────────────────────────────────────┘


不严格地说,==相等比较

如果您使用的是==运算符,或者使用松散比较的任何其他比较运算符,如!=<>==,那么您总是需要查看上下文来查看转换的内容、位置和原因,以了解发生了什么。

转换规则

  • 转换为布尔值
  • 转换为整数
  • 转换为浮动
  • 转换为字符串
  • 转换为数组
  • 转换为对象
  • 转换为资源
  • 转换为空

类型比较表

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

Loose comparisons with ==

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
┌─────────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┬─────────┬───────┬───────┐
│         │ TRUE  │ FALSE │   1   │   0   │  -1   │ "1"  │ "0"  │"-1"  │ NULL  │ array()"php"""   │
├─────────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┼─────────┼───────┼───────┤
TRUE    │ TRUE  │ FALSETRUE  │ FALSETRUE  │ TRUE  │ FALSETRUE  │ FALSEFALSE   │ TRUE  │ FALSE
FALSE   │ FALSETRUE  │ FALSETRUE  │ FALSEFALSETRUE  │ FALSETRUE  │ TRUE    │ FALSETRUE  │
1       │ TRUE  │ FALSETRUE  │ FALSEFALSETRUE  │ FALSEFALSEFALSEFALSE   │ FALSEFALSE
0       │ FALSETRUE  │ FALSETRUE  │ FALSEFALSETRUE  │ FALSETRUE  │ FALSE   │ TRUE  │ TRUE  │
-1      │ TRUE  │ FALSEFALSEFALSETRUE  │ FALSEFALSETRUE  │ FALSEFALSE   │ FALSEFALSE
"1"     │ TRUE  │ FALSETRUE  │ FALSEFALSETRUE  │ FALSEFALSEFALSEFALSE   │ FALSEFALSE
"0"     │ FALSETRUE  │ FALSETRUE  │ FALSEFALSETRUE  │ FALSEFALSEFALSE   │ FALSEFALSE
"-1"    │ TRUE  │ FALSEFALSEFALSETRUE  │ FALSEFALSETRUE  │ FALSEFALSE   │ FALSEFALSE
NULL    │ FALSETRUE  │ FALSETRUE  │ FALSEFALSEFALSEFALSETRUE  │ TRUE    │ FALSETRUE  │
array()FALSETRUE  │ FALSEFALSEFALSEFALSEFALSEFALSETRUE  │ TRUE    │ FALSEFALSE
"php"   │ TRUE  │ FALSEFALSETRUE  │ FALSEFALSEFALSEFALSEFALSEFALSE   │ TRUE  │ FALSE
""      │ FALSETRUE  │ FALSETRUE  │ FALSEFALSEFALSEFALSETRUE  │ FALSE   │ FALSETRUE  │
└─────────┴───────┴───────┴───────┴───────┴───────┴───────┴───────┴───────┴───────┴─────────┴───────┴───────┘

严格的===相同比较

如果您使用的是===运算符,或者任何其他使用严格比较的比较运算符,如!=====,那么您总是可以确保类型不会发生神奇的变化,因为不会发生转换。因此,通过严格的比较,类型和值必须相同,而不仅仅是值。

类型比较表

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

Strict comparisons with ===

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
┌─────────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┬─────────┬───────┬───────┐
│         │ TRUE  │ FALSE │   1   │   0   │  -1   │ "1"  │ "0"  │"-1"  │ NULL  │ array()"php"""   │
├─────────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┼─────────┼───────┼───────┤
TRUE    │ TRUE  │ FALSEFALSEFALSEFALSEFALSEFALSEFALSEFALSEFALSE   │ FALSEFALSE
FALSE   │ FALSETRUE  │ FALSEFALSEFALSEFALSEFALSEFALSEFALSEFALSE   │ FALSEFALSE
1       │ FALSEFALSETRUE  │ FALSEFALSEFALSEFALSEFALSEFALSEFALSE   │ FALSEFALSE
0       │ FALSEFALSEFALSETRUE  │ FALSEFALSEFALSEFALSEFALSEFALSE   │ FALSEFALSE
-1      │ FALSEFALSEFALSEFALSETRUE  │ FALSEFALSEFALSEFALSEFALSE   │ FALSEFALSE
"1"     │ FALSEFALSEFALSEFALSEFALSETRUE  │ FALSEFALSEFALSEFALSE   │ FALSEFALSE
"0"     │ FALSEFALSEFALSEFALSEFALSEFALSETRUE  │ FALSEFALSEFALSE   │ FALSEFALSE
"-1"    │ FALSEFALSEFALSEFALSEFALSEFALSEFALSETRUE  │ FALSEFALSE   │ FALSEFALSE
NULL    │ FALSEFALSEFALSEFALSEFALSEFALSEFALSEFALSETRUE  │ FALSE   │ FALSEFALSE
array()FALSEFALSEFALSEFALSEFALSEFALSEFALSEFALSEFALSETRUE    │ FALSEFALSE
"php"   │ FALSEFALSEFALSEFALSEFALSEFALSEFALSEFALSEFALSEFALSE   │ TRUE  │ FALSE
""      │ FALSEFALSEFALSEFALSEFALSEFALSEFALSEFALSEFALSEFALSE   │ FALSETRUE  │
└─────────┴───────┴───────┴───────┴───────┴───────┴───────┴───────┴───────┴───────┴─────────┴───────┴───────┘


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

实例:

1
2
3
4
5
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

警告:具有等效成员的同一类的两个实例与===运算符不匹配。例子:

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


一幅画胜过千言万语:

php double等于==等同性图:

enter image description here

php triple等于===等同性图:

enter image description here

创建这些图像的源代码:

https://github.com/sentinentmachine/php_equality_图表

大师冥想

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

  • NAN != NAN,但NAN == true
  • 如果left是数字,==将把左、右操作数转换为数字。所以123 =="123foo",但是"123" !="123foo"
  • 引号中的十六进制字符串偶尔是一个浮点数,它将被意外地强制转换为违背您的意愿的浮点数,从而导致运行时错误。

  • ==是不可传递的,因为"0"== 00 ==""但是"0" !=""是可传递的。

  • 尚未声明的php变量是假的,尽管php有一种表示未定义变量的方法,但该功能已被==禁用。
  • "6" ==" 6""4.2" =="4.20""133" =="0133",但133 != 0133。但是"0x10" =="16""1e3" =="1000"暴露出意外的字符串转换为八进制将在没有您的指令或同意的情况下发生,从而导致运行时错误。

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

  • 当数字足够大时,它们就等于无穷大。

  • 一个新的类是==到1。

  • 错误是最危险的值,因为对于大多数其他变量来说,错误是==的,大多数情况下会破坏它的目的。
  • 希望:

    如果使用php,则不应使用double equals运算符,因为如果使用triple equals,则唯一需要担心的边缘情况是NaN和接近无穷大的数字,它们被强制转换为无穷大。有了双等号,任何事物都会对任何事物或事物感到惊讶,或是对你的意愿和你的意愿感到惊讶,而这两者显然是相等的。

    在PHP中使用==的任何地方都是一种糟糕的代码味道,因为其中的85个错误是由隐式的强制转换规则暴露出来的,而隐式强制转换规则似乎是由数百万程序员通过Brownian Motion编程设计的。


    关于javascript:

    ===运算符的工作方式与==运算符相同,但它要求其操作数不仅具有相同的值,而且具有相同的数据类型。

    例如,下面的示例将显示"x和y相等",但不显示"x和y相同"。

    1
    2
    3
    4
    5
    6
    7
    8
    var x = 4;
    var y = '4';
    if (x == y) {
        alert('x and y are equal');
    }
    if (x === y) {
        alert('x and y are identical');
    }


    关于对象比较的其他答案的补充:

    ==使用对象名称及其值比较对象。如果两个对象的类型相同且成员值相同,则$a == $b生成true。

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    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


    简单来说:

    ==检查是否等效(仅限值)

    ==检查是否相同(值和类型)

    等效与相同:类比

    1+1=2+0(等效)

    1+1=1+1(相同)

    在PHP中:

    真==1(真-等值)

    true==1(false-值和类型不相同)

    • 布尔是真的
    • 1是int


    这都是关于数据类型的。以BOOL为例(对或错):

    true也等于1false也等于0

    在比较时,==不关心数据类型:所以如果你有一个变量是1(也可以是true):

    $var=1;

    然后与==比较:

    1
    2
    3
    4
    if ($var == true)
    {
        echo"var is true";
    }

    $var实际上并不等于true对吗?它的int值为1,反过来等于true。

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

    如果我做到了

    1
    2
    3
    4
    if ($var === true)
    {
        echo"var is true";
    }

    这种情况不会是真的,因为$var !== true,只有== true(如果你知道我的意思的话)。

    你为什么需要这个?

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

    array_search()函数只搜索数组中的一个值,并返回该值所在元素的键。如果在数组中找不到该值,则返回false。但是,如果您对存储在数组第一个元素(该元素的数组键为0)中的值执行了array_search(),会怎么样呢?array_search()函数将返回0…等于false。

    如果你这样做:

    1
    2
    3
    4
    5
    6
    7
    $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完全相同,所以如果您这样做了:

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

    因此,对于这种情况,您将使用===,以便检查数据类型。


    例如,数据库属性可以为空或":

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    $attributeFromArray ="";
    if ($attributeFromArray == ""){}  //true
    if ($attributeFromArray ===""){}  //true
    if ($attributeFromArray ==  null){}  //true
    if ($attributeFromArray === null){}  //false

    $attributeFromArray = null;
    if ($attributeFromArray == ""){}  //true
    if ($attributeFromArray ===""){}  //false
    if ($attributeFromArray ==  null){}  //true
    if ($attributeFromArray === null){}  //true

    x = 5为例

    1)运算符:==为"等于"。x == 8是假的2)运算符:==为"完全等于"(值和类型),x === 5为真,x ==="5"为假。


    很少有这样的例子

    1
    2
    3
    4
    var_dump(5 == 5);    // True
    var_dump(5 =="5");  // True because == checks only same value not type
    var_dump(5 === 5);   // True
    var_dump(5 ==="5"); // False because value are same but data type are different.

    附笔。

    == Compares the value only, it won't bother about the data types

    VS

    === Compares the values and data types


    简而言之,==

    PHP允许您进行真正意义不大的比较。例子:

    1
    2
    3
    4
    $y ="wauv";
    $x = false;
    if ($x == $y)
        ...

    虽然这允许一些有趣的"快捷方式",但您应该注意,因为返回不应该返回的内容的函数(如"错误"而不是数字)不会被捕获,您将不知道发生了什么。

    在php中,==比较值并在必要时执行类型转换(例如,在整数比较中,字符串"12343sdfjskfjds"将变为"12343")。==将比较值和类型,如果类型不同,则返回false。

    如果您在PHP手册中看到,如果函数失败,很多函数都会返回"false",但在成功的情况下,它们可能会返回0,这就是为什么它们建议执行"if(function()!==false)"以避免错误。


    1
    2
    3
    4
    5
    6
    $a = 5;   // 5 as an integer

    var_dump($a == 5);       // compare value; return true
    var_dump($a == '5');     // compare value (ignore type); return true
    var_dump($a === 5);      // compare type/value (integer vs. integer); return true
    var_dump($a === '5');    // compare type/value (integer vs. string); return false

    不过要小心。这是一个众所周知的问题。

    1
    2
    3
    4
    // 'test' is found at position 0, which is interpreted as the boolean 'false'
    if (strpos('testing', 'test')) {
        // code...
    }

    VS

    1
    2
    3
    4
    // true, as strict comparison was made (0 !== false)
    if (strpos('testing', 'test') !== false) {
        // code...
    }


    php==是比较变量值的比较运算符。但是==比较值和数据类型。

    例如,

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <?php
      $var1 = 10;
      $var2 = '10';

      if($var1 == $var2) {
        echo 'Variables are equal';
      } else {
        echo 'Variables are not equal';
      }
    ?>

    在这种情况下,输出将是"变量相等",即使它们的数据类型不同。

    但是如果我们使用==而不是==,输出将是"变量不相等"。PHP首先比较变量的值,然后比较数据类型。这里的值相同,但数据类型不同。


    PHP是一种松散类型的语言。使用double equal运算符可以对变量进行松散检查。

    松散地检查一个值将允许一些类似但不相等的值等同于相同的值:

    • 无效的

    使用双等号运算符,所有这些值都将等于相等。


    至于何时使用其中一个,以PHP中的fwrite()函数为例。

    此函数将内容写入文件流。根据php,"fwrite()返回写入的字节数,或者出错时返回false。"。如果要测试函数调用是否成功,则此方法存在缺陷:

    1
    2
    3
    4
    if (!fwrite(stuff))
    {
        log('error!');
    }

    它可以返回零(并且被认为是成功的),并且您的条件仍然会被触发。正确的方法是:

    1
    2
    3
    4
    if (fwrite(stuff) === FALSE)
    {
        log('error!');
    }


    您将使用==来测试函数或变量是否为假,而不仅仅是等于假(零或空字符串)。

    1
    2
    3
    4
    5
    6
    7
    8
    $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。

    1
    if ($pos == false)

    1
    if (!$pos)

    这不是你想要的。


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    <?php

        /**
         * Comparison of two PHP objects                         ==     ===
         * Checks for
         * 1. References                                         yes    yes
         * 2. Instances with matching attributes and its values  yes    no
         * 3. Instances with different attributes                yes    no
         **/


        // There is no need to worry about comparing visibility of property or
        // method, because it will be the same whenever an object instance is
        // created, however visibility of an object can be modified during run
        // time using ReflectionClass()
        // http://php.net/manual/en/reflectionproperty.setaccessible.php
        //
        class Foo
        {
            public $foobar = 1;

            public function createNewProperty($name, $value)
            {
                $this->{$name} = $value;
            }
        }

        class Bar
        {
        }
        // 1. Object handles or references
        // Is an object a reference to itself or a clone or totally a different object?
        //
        //   ==  true   Name of two objects are same, for example, Foo() and Foo()
        //   ==  false  Name of two objects are different, for example, Foo() and Bar()
        //   === true   ID of two objects are same, for example, 1 and 1
        //   === false  ID of two objects are different, for example, 1 and 2

        echo"1. Object handles or references (both == and    ===) <br />";

        $bar = new Foo();    // New object Foo() created
        $bar2 = new Foo();   // New object Foo() created
        $baz = clone $bar;   // Object Foo() cloned
        $qux = $bar;         // Object Foo() referenced
        $norf = new Bar();   // New object Bar() created
        echo"bar";
        var_dump($bar);
        echo"baz";
        var_dump($baz);
        echo"qux";
        var_dump($qux);
        echo"bar2";
        var_dump($bar2);
        echo"norf";
        var_dump($norf);

        // Clone: == true and === false
        echo '$bar == $bar2';
        var_dump($bar == $bar2); // true

        echo '$bar === $bar2';
        var_dump($bar === $bar2); // false

        echo '$bar == $baz';
        var_dump($bar == $baz); // true

        echo '$bar === $baz';
        var_dump($bar === $baz); // false

        // Object reference: == true and === true
        echo '$bar == $qux';
        var_dump($bar == $qux); // true

        echo '$bar === $qux';
        var_dump($bar === $qux); // true

        // Two different objects: == false and === false
        echo '$bar == $norf';
        var_dump($bar == $norf); // false

        echo '$bar === $norf';
        var_dump($bar === $norf); // false

        // 2. Instances with matching attributes and its values (only ==).
        //    What happens when objects (even in cloned object) have same
        //    attributes but varying values?

        // $foobar value is different
        echo"2. Instances with matching attributes  and its values (only ==) <br />";

        $baz->foobar = 2;
        echo '$foobar' ." value is different <br />";
        echo '$bar->foobar = ' . $bar->foobar ."<br />";
        echo '$baz->foobar = ' . $baz->foobar ."<br />";
        echo '$bar == $baz';
        var_dump($bar == $baz); // false

        // $foobar's value is the same again
        $baz->foobar = 1;
        echo '$foobar' ." value is the same again <br />";
        echo '$bar->foobar is ' . $bar->foobar ."<br />";
        echo '$baz->foobar is ' . $baz->foobar ."<br />";
        echo '$bar == $baz';
        var_dump($bar == $baz); // true

        // Changing values of properties in $qux object will change the property
        // value of $bar and evaluates true always, because $qux = &$bar.
        $qux->foobar = 2;
        echo '$foobar value of both $qux and $bar is 2, because $qux = &$bar' ."<br />";
        echo '$qux->foobar is ' . $qux->foobar ."<br />";
        echo '$bar->foobar is ' . $bar->foobar ."<br />";
        echo '$bar == $qux';
        var_dump($bar == $qux); // true

        // 3. Instances with different attributes (only ==)
        //    What happens when objects have different attributes even though
        //    one of the attributes has same value?
        echo"3. Instances with different attributes (only ==) <br />";

        // Dynamically create a property with the name in $name and value
        // in $value for baz object
        $name = 'newproperty';
        $value = null;
        $baz->createNewProperty($name, $value);
        echo '$baz->newproperty is ' . $baz->{$name};
        var_dump($baz);

        $baz->foobar = 2;
        echo '$foobar' ." value is same again <br />";
        echo '$bar->foobar is ' . $bar->foobar ."<br />";
        echo '$baz->foobar is ' . $baz->foobar ."<br />";
        echo '$bar == $baz';
        var_dump($bar == $baz); // false
        var_dump($bar);
        var_dump($baz);
    ?>

    ===操作符应该比较精确的内容相等,而==操作符应该比较语义相等。特别是它将强制字符串为数字。

    平等是一个广泛的主题。参见维基百科关于平等的文章。


    到目前为止,所有的答案都忽略了一个危险的问题,即==。在传递中注意到整数和double是不同的类型,但不强调,因此下面的代码是:

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

    给予:

    1
    2
     equal
     not equal

    注意,这不是"舍入误差"的情况。这两个数字与最后一位完全相等,但它们的类型不同。

    这是一个棘手的问题,因为如果所有的数字都足够小(其中"足够小"取决于运行的硬件和操作系统),使用==的程序可以运行数年。但是,如果一个整数恰好足够大,可以转换为double,则它的类型将"永久"更改,即使后续操作或许多操作可能会使其返回到一个小的值整数。而且,情况更糟。它可以传播-双尼斯感染可以通过它接触到的任何东西,一次一个计算。

    在现实世界中,这在处理2038年之后日期的程序中可能是一个问题。此时,Unix时间戳(1970-01-01 00:00:00 UTC以来的秒数)将需要32位以上,因此在某些系统上,它们的表示将"神奇地"切换到双倍。因此,如果你计算两次之间的差额,你可能会得到几秒钟的时间,但结果是双倍的,而不是2017年的整数结果。

    我认为这比字符串和数字之间的转换更糟糕,因为它很微妙。我发现跟踪什么是字符串,什么是数字很容易,但是跟踪数字中的位数是我无法理解的。

    所以,在上面的答案中有一些很好的表格,但是1(作为整数)和1(微妙的双精度)和1.0(明显的双精度)之间没有区别。另外,应该始终使用==和never==的建议并不好,因为==有时会在==正常工作时失败。另外,javascript在这方面也不是等价的,因为它只有一个数字类型(在内部它可能有不同的位表示,但它不会导致==的问题)。

    我的建议-两者都不要用。您需要编写自己的比较函数来真正修复这一混乱局面。


    变量有一个类型和一个值。

    • $var="test"是包含"test"的字符串
    • $var2=24是一个整数,vhose值为24。

    当您使用这些变量(在PHP中)时,有时您没有好的类型。例如,如果你这样做

    1
    if ($var == 1) {... do something ...}

    PHP必须将("to cast")$var转换为整数。在这种情况下,"$var==1"为真,因为任何非空字符串都被强制转换为1。

    使用==时,检查值和类型是否相等,因此"$var==1"为假。

    这很有用,例如,当您有一个函数可以返回false(出错时)和0(结果时):

    1
    if(myFunction() == false) { ... error on myFunction ... }

    这段代码是错误的,好像myFunction()返回0,它被强制转换为false,而您似乎有一个错误。正确的代码是:

    1
    if(myFunction() === false) { ... error on myFunction ... }

    因为测试是返回值"是一个布尔值且为假",而不是"可以强制转换为假"。


    在PHP数组和对象中,=====有两个不同之处,我认为这里没有提到;两个键排序不同的数组和对象。

    两个不同键排序的数组

    如果您有一个具有键排序的数组和另一个具有不同键排序的数组,那么它们是完全不同的(即使用===)。这可能会导致对数组进行键排序,并尝试将排序后的数组与原始数组进行比较。

    例如,考虑一个空数组。首先,我们尝试在不进行任何特殊排序的情况下将一些新索引推送到数组中。一个很好的例子是使用字符串作为键的数组。现在深入到一个例子中:

    1
    2
    3
    4
    5
    6
    7
    // Define an array
    $arr = [];

    // Adding unsorted keys
    $arr["I"] ="we";
    $arr["you"] ="you";
    $arr["he"] ="they";

    现在,我们有一个未排序的键数组(例如,"he"在"you"后面)。考虑相同的数组,但我们按字母顺序对其键进行排序:

    1
    2
    3
    4
    5
    6
    7
    // Declare array
    $alphabetArr = [];

    // Adding alphabetical-sorted keys
    $alphabetArr["I"] ="we";
    $alphabetArr["he"] ="they";
    $alphabetArr["you"] ="you";

    提示:可以使用ksort()函数按键对数组进行排序。

    现在,您有了另一个与第一个数组具有不同键排序的数组。因此,我们将对它们进行比较:

    1
    2
    $arr == $alphabetArr; // true
    $arr === $alphabetArr; // false

    注意:这可能很明显,但是使用严格比较比较两个不同的数组总是会得到false。然而,使用===或不使用EDOCX1,两个任意数组可能相等。

    你会说:"这种差异是可以忽略的。"然后我说这是一个区别,应该考虑,而且可能随时发生。如上所述,对数组中的键进行排序就是一个很好的例子。

    物体

    记住,两个不同的对象永远不会严格相等。这些例子将有助于:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    $stdClass1 = new stdClass();
    $stdClass2 = new stdClass();
    $clonedStdClass1 = clone $stdClass1;

    // Comparing
    $stdClass1 == $stdClass2; // true
    $stdClass1 === $stdClass2; // false
    $stdClass1 == $clonedStdClass1; // true
    $stdClass1 === $clonedStdClass1; // false

    注意:将一个对象分配给另一个变量并不会创建一个副本,而是创建一个对与该对象相同内存位置的引用。请看这里。

    注意:从php7开始,添加了匿名类。从结果来看,在上述试验中,new class {}new stdClass()之间没有差异。