首页 文章

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

提问于
浏览
444

===== 之间有什么区别?

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

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

什么是有用的例子?

20 回答

  • 0

    一个例子是数据库属性可以为null或“”:

    $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
    
  • 21

    鉴于 x = 5

    1)运算符:==是"equal to" . x == 8 是假的
    2)运算符:===是"exactly equal to"(值和类型) x === 5 为真, x === "5" 为假

  • 2

    几个例子

    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.
    

    附:

    ==仅比较值,它不会打扰数据类型

    ===比较值和数据类型

  • 2

    ==和===之间的差异

    松散 == 等于运算符和严格 === 相同运算符之间的区别在manual中有详细解释:

    比较运算符┌─────────────────────────────────────────────────────────────────────────────────────── ────────────────────────────────────┐
    │例子│姓名│结果│
    ├──────────┼───────────┼────────────────────────── ─────────────────────────────────┤
    │$ a == $b│Equal│如果在类型杂耍后$ a等于$ b,则为TRUE . │
    │$ a === $b│相同│如果$ a等于$ b,则为TRUE,它们属于同一类型 . │
    └──────────┴───────────┴────────────────────────── ─────────────────────────────────┘


    宽松==平等比较

    如果您正在使用 == 运算符,或使用松散比较的任何其他比较运算符,例如 !=<>== ,您始终必须查看 context 以查看转换内容的内容,位置和原因,以了解正在发生的事情 .

    转换规则

    类型比较表

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

    与==┌────────────────────────────────────────────────────────────────────────────────────────────────────── ──────┬───────┬───────┬───────┬───────┬─────────┬─ ──────┬───────┐
    ││TRUE│FALSE│1│0│-1│“1”│“0”│“-1”│NULL│数组()│“php”│“”│
    ├─────────┼───────┼───────┼───────┼───────┼─────── ┼───────┼───────┼───────┼───────┼─────────┼─────── ┼───────┤
    │正确│正确│错误│正确│错误│正确│正确│错误│正确│错误│错误│正确│错误│
    │错误│错误│正确│错误│正确│错误│错误│正确│错误│正确│正确│错误│正确│
    │1│TRUE│FALSE│TRUE│FALSE│FALSE│TRUE│FALSE│FALSE│FALSE│FALSE│FALSE│FALSE│
    │0│FALSE│TRUE│FALSE│TRUE│FALSE│FALSE│TRUE│FALSE│TRUE│FALSE│TRUE│TRUE│
    │-1│TRUE│FALSE│FALSE│FALSE│TRUE│FALSE│FALSE│TRUE│FALSE│FALSE│FALSE│FALSE│
    │“1”│TRUE│FALSE│TRUE│FALSE│FALSE│TRUE│FALSE│FALSE│FALSE│FALSE│FALSE│FALSE│
    │“0”│错误│正确│错误│正确│错误│错误│正确│错误│错误│错误│错误│错误│
    │“-1”│TRUE│FALSE│FALSE│FALSE│TRUE│FALSE│FALSE│TRUE│FALSE│FALSE│FALSE│FALSE│
    │NULL│FALSE│TRUE│FALSE│TRUE│FALSE│FALSE│FALSE│FALSE│TRUE│TRUE│FALSE│TRUE│
    │数组()│错误│正确│错误│错误│错误│错误│错误│错误│正确│正确│错误│错误│
    │“php”│TRUE│FALSE│FALSE│TRUE│FALSE│FALSE│FALSE│FALSE│FALSE│FALSE│TRUE│FALSE│
    │“”│错误│正确│错误│正确│错误│错误│错误│错误│正确│错误│错误│正确│
    └─────────┴───────┴───────┴───────┴───────┴─────── ┴───────┴───────┴───────┴───────┴─────────┴─────── ┴───────┘

    严格===相同的比较

    如果您正在使用 === 运算符或任何其他使用严格比较的比较运算符,例如 !===== ,那么您始终可以确保类型不会神奇地改变,因为不会进行转换 . 因此,通过严格比较,类型和值必须相同,而不仅仅是值 .

    类型比较表

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

    严格比较===┌───────────────────────────────── ───────┬───────┬───────┬───────┬───────┬─────────┬ ───────┬───────┐
    ││TRUE│FALSE│1│0│-1│“1”│“0”│“-1”│NULL│数组()│“php”│“”│
    ├─────────┼───────┼───────┼───────┼───────┼─────── ┼───────┼───────┼───────┼───────┼─────────┼─────── ┼───────┤
    │TRUE│TRUE│FALSE│FALSE│FALSE│FALSE│FALSE│FALSE│FALSE│FALSE│FALSE│FALSE│FALSE│
    │错误│错误│正确│错误│错误│错误│错误│错误│错误│错误│错误│错误│错误│
    │1│FALSE│FALSE│TRUE│FALSE│FALSE│FALSE│FALSE│FALSE│FALSE│FALSE│FALSE│FALSE│
    │0│FALSE│FALSE│FALSE│TRUE│FALSE│FALSE│FALSE│FALSE│FALSE│FALSE│FALSE│FALSE│
    │-1│FALSE│FALSE│FALSE│FALSE│TRUE│FALSE│FALSE│FALSE│FALSE│FALSE│FALSE│FALSE│
    │“1”│错误│错误│错误│错误│错误│正确│错误│错误│错误│错误│错误│错误│
    │“0”│错误│错误│错误│错误│错误│错误│正确│错误│错误│错误│错误│错误│
    │“-1”│错误│错误│错误│错误│错误│错误│错误│正确│错误│错误│错误│错误│
    │NULL│FALSE│FALSE│FALSE│FALSE│FALSE│FALSE│FALSE│FALSE│TRUE│FALSE│FALSE│FALSE│
    │数组()│错误│错误│错误│错误│错误│错误│错误│错误│错误│正确│错误│错误│
    │“php”│错误│错误│错误│错误│错误│错误│错误│错误│错误│错误│正确│错误│
    │“”│错误│错误│错误│错误│错误│错误│错误│错误│错误│错误│错误│正确│
    └─────────┴───────┴───────┴───────┴───────┴─────── ┴───────┴───────┴───────┴───────┴─────────┴─────── ┴───────┘

  • 1

    如果运算符不同,则运算符==在两种不同类型之间进行转换,而===运算符执行“类型安全比较” . 这意味着如果两个操作数具有相同的类型和相同的值,它将仅返回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
    

    Warning :具有等效成员的同一个类的两个实例与 === 运算符不匹配 . 例:

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

    一张图片胜过千言万语:

    PHP Double Equals ==平等图表:

    enter image description here

    PHP Triple Equals === Equality chart:

    enter image description here

    创建这些图像的源代码:

    https://github.com/sentientmachine/php_equality_charts

    大师冥想

    那些希望保持理智的人,不要再读了 .

    • '=='尽可能将左右操作数转换为数字(123 == "123foo",但"123"!= "123foo"

    • 引号中的十六进制字符串偶尔会浮动,并将根据您的意愿转换为它 .

    • ==不可传递,因为("0" = = 0到0,0是==到“" but " 0 " != "”)

    • "6" == " 6","4.2" == "4.20",和"133" == "0133" . 但是133!= 0133,因为0133是八进制的 . 但"0x10" == "16"和"1e3" == "1000"

    • 尚未声明的PHP变量为false .

    • False等于0,blankstring和空数组和“0” .

    • 当数字足够大时,它们是==无穷大 .

    • NAN不==本身,但它是真的 .

    • 一个新类是==到1 .

    • False是最危险的值,因为对于大多数其他变量,False ==,大多数都是为了达到它的目的 .

    希望:

    如果您使用PHP,则不应使用double equals运算符,始终使用triple equals .

  • 53

    关于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');
    }
    
  • 12

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

    ==使用对象的名称及其值来比较对象 . 如果两个对象具有相同的类型且具有相同的成员值,则 $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
    
  • 0

    简单来说:

    == checks if equivalent (value only)

    === checks if the same (value && type)

    等价与相同:类比

    1 + 1 = 2 + 0 (等效)

    1 + 1 = 1 + 1 (同)

    在PHP中:

    true == 1 (真 - 相当于 Value )

    true === 1 (false - 值&&类型不一样)

    • boolean

    • 1是 int

  • 577

    这都是关于数据类型的 . 以 BOOL (真或假)为例:

    true 也等于 1false 也等于 0

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

    $var=1;

    然后与 == 进行比较:

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

    $var 实际上并不等于 true ,是吗?它的int值为 1 ,而后者又等于true .

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

    所以,如果我这样做

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

    那个条件不会是真的,因为 $var !== true 它只是 == true (如果你知道我的意思) .

    你为什么需要这个?

    简单 - 让's take a look at one of PHP'的函数: array_search()

    array_search() 函数只是在数组中搜索一个值,并返回找到该值的元素的键 . 如果在数组中找不到该值,则返回 false . 但是,如果你对 first element of the array (其数组键为 0 )存储的值执行了 array_search() ,那么 array_search() 函数将返回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)
    

    因此,对于类似的事情,您将使用 === ,以便检查数据类型 .

  • 38
    $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
    

    但要小心 . 这是一个臭名昭着的问题 .

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

    // true, as strict comparison was made (0 !== false)
    if (strpos('testing', 'test') !== false) {
        // code...
    }
    
  • 8

    简而言之,===的工作方式与大多数其他编程语言中的==相同 .

    PHP允许您进行真正有意义的比较 . 例:

    $y = "wauv";
    $x = false;
    if ($x == $y)
        ...
    

    虽然这允许一些有趣的“快捷方式”,但你应该注意,因为一个不应该返回的东西(比如“错误”而不是数字)不会被捕获,你会想知道发生了什么 .

    在PHP中,==比较值并在必要时执行类型转换(例如,字符串“12343sdfjskfjds”在整数比较中将变为“12343”) . ===将比较值AND类型,如果类型不相同则返回false .

    如果您查看PHP手册,您将看到许多函数在函数失败时返回“false”,但它们可能在成功的场景中返回0,这就是为什么他们建议执行“if(function()!==错误)“避免错误 .

  • 8

    您可以使用===来测试函数或变量是否为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)
    

    这不是你想要的 .

  • 3

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

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

    if (!fwrite(stuff))
    {
        log('error!');
    }
    

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

    if (fwrite(stuff) === FALSE)
    {
        log('error!');
    }
    
  • 2

    PHP是一种松散类型的语言 . 使用双等运算符可以对变量进行宽松的检查 .

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

    • ''

    • null

    • 0

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

  • 1

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

    • $ var = "test"是一个包含"test"的字符串

    • $ var2 = 24是一个整数vhose值是24 .

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

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

    PHP必须将$ var转换为“整数” . 在这种情况下,“$ var == 1”为true,因为任何非空字符串都会转换为1 .

    使用===时,检查值AND THE TYPE是否相等,因此“$ var === 1”为false .

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

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

    此代码错误,好像 myFunction() 返回0,它被转换为false并且您似乎有错误 . 正确的代码是:

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

    因为测试是返回值“是布尔值并且是假的”而不是“可以转换为假” .

  • 1

    === 运算符应该在 == 运算符时比较确切的内容相等性会比较语义上的平等 . 特别是它会将字符串强制转换为数字 .

    平等是一个广泛的主题 . 见the Wikipedia article on equality .

  • 4
    <?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    ===) 
    "; $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 ==)
    "; $baz->foobar = 2; echo '$foobar' . " value is different
    "; echo '$bar->foobar = ' . $bar->foobar . "
    "; echo '$baz->foobar = ' . $baz->foobar . "
    "; 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
    "; echo '$bar->foobar is ' . $bar->foobar . "
    "; echo '$baz->foobar is ' . $baz->foobar . "
    "; 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' . "
    "; echo '$qux->foobar is ' . $qux->foobar . "
    "; echo '$bar->foobar is ' . $bar->foobar . "
    "; 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 ==)
    "; // 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
    "; echo '$bar->foobar is ' . $bar->foobar . "
    "; echo '$baz->foobar is ' . $baz->foobar . "
    "; echo '$bar == $baz'; var_dump($bar == $baz); // false var_dump($bar); var_dump($baz); ?>
  • 232

    到目前为止,所有答案都忽略了===的危险问题 . 已经注意到,但是没有强调,integer和double是不同的类型,因此以下代码:

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

    得到:

    equal
     not equal
    

    请注意,这不是“舍入错误”的情况 . 这两个数字完全相同,直到最后一位,但它们有不同的类型 .

    这是一个令人讨厌的问题,因为如果所有数字足够小(使用“足够小”取决于您运行的硬件和操作系统),使用===的程序可以快乐地运行多年 . 但是,如果偶然,整数恰好大到足以转换为double,则其类型将“永久”更改,即使后续操作或许多操作可能会将其返回到值中的小整数 . 而且,它变得更糟 . 它可以传播 - 双重感染可以传递到它触及的任何东西,一次一个计算 .

    例如,在现实世界中,这可能是处理2038年以后日期的程序中的问题 . 此时,UNIX时间戳(自1970-01-01 00:00:00 UTC以来的秒数)将需要超过32位,因此它们的表示将在某些系统上“神奇地”切换为双精度 . 因此,如果计算两次之间的差异,可能会以几秒钟结束,但作为一个双倍,而不是2017年发生的整数结果 .

    我认为这比字符串和数字之间的转换要糟糕得多,因为它很微妙 . 我发现很容易跟踪什么是字符串和什么是数字,但是跟踪数字中的位数是超出我的 .

    因此,在上面的答案中有一些很好的表,但没有区分1(作为整数)和1(微妙的双)和1.0(明显的双) . 此外,建议您应该始终使用===和never ==并不是很好,因为===有时会失败,其中==正常工作 . 此外,JavaScript在这方面并不相同,因为它只有一种数字类型(在内部它可能有不同的逐位表示,但它不会导致===的问题) .

    我的建议 - 两者都不用 . 你需要编写自己的比较函数来真正解决这个问题 .

  • 6

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

    具有不同键排序的两个数组

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

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

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

    现在,我们有一个not-sorted-keys数组(例如''他'来自'你') . 考虑相同的数组,但我们按字母顺序对其键进行排序:

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

    Tip :您可以使用ksort()函数按键对数组进行排序 .

    现在你有另一个数组与第一个数组有不同的键排序 . 所以,我们要比较它们:

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

    Note :可能很明显,但使用严格比较比较两个不同的数组总是会产生 false . 但是,使用 === 可以使两个任意数组相等 .

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

    物体

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

    $stdClass1 = new stdClass();
    $stdClass2 = new stdClass();
    $clonedStdClass1 = clone $stdClass1;
    
    // Comparing
    $stdClass1 == $stdClass2; // true
    $stdClass1 === $stdClass2; // false
    $stdClass1 == $clonedStdClass1; // true
    $stdClass1 === $clonedStdClass1; // false
    

    Note :将对象分配给另一个变量不会创建副本 - 而是创建对与该对象相同的内存位置的引用 . See here .

    Note :自PHP7起,添加了anonymous classes . 从结果来看,上述测试中 new class {}new stdClass() 之间没有区别 .

相关问题