PHP等式(== double等于)和identity(=== triple等于)比较运算符有什么不同?


=====什么区别?

  • 松散==比较工作到底如何?
  • 严格===比较是如何工作的?

什么是一些有用的例子?



Answers


=====之间的区别

松散==相等运算符和严格===相同运算符之间的区别在手册中有详细说明:

比较运算符

┌──────────┬───────────┬───────────────────────────────────────────────────────────┐
│ 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. │
└──────────┴───────────┴───────────────────────────────────────────────────────────┘

松散==相等的比较

如果您使用的是==运算符或其他使用松散比较的比较运算符(例如!=<>== ,则必须查看上下文以查看哪些内容以及为什么要转换为了解什么正在进行。

转换规则

类型比较表

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

==进行比较

┌─────────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┬─────────┬───────┬───────┐
│         │ TRUE  │ FALSE │   1   │   0   │  -1   │  "1"  │  "0"  │ "-1"  │ NULL  │ array() │ "php" │  ""   │
├─────────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┼─────────┼───────┼───────┤
│ TRUE    │ TRUE  │ FALSE │ TRUE  │ FALSE │ TRUE  │ TRUE  │ FALSE │ TRUE  │ FALSE │ FALSE   │ TRUE  │ FALSE │
│ FALSE   │ FALSE │ TRUE  │ FALSE │ TRUE  │ FALSE │ FALSE │ TRUE  │ FALSE │ TRUE  │ TRUE    │ FALSE │ TRUE  │
│ 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"     │ FALSE │ TRUE  │ FALSE │ TRUE  │ FALSE │ FALSE │ TRUE  │ FALSE │ FALSE │ FALSE   │ FALSE │ FALSE │
│ "-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  │
│ array() │ FALSE │ TRUE  │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ TRUE  │ TRUE    │ FALSE │ FALSE │
│ "php"   │ TRUE  │ FALSE │ FALSE │ TRUE  │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE   │ TRUE  │ FALSE │
│ ""      │ FALSE │ TRUE  │ FALSE │ TRUE  │ FALSE │ FALSE │ FALSE │ FALSE │ TRUE  │ FALSE   │ FALSE │ 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 │ 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"     │ 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 │ FALSE │ FALSE │ FALSE │ TRUE  │ FALSE │ FALSE   │ FALSE │ FALSE │
│ NULL    │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ TRUE  │ FALSE   │ FALSE │ FALSE │
│ array() │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ TRUE    │ FALSE │ FALSE │
│ "php"   │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE   │ TRUE  │ FALSE │
│ ""      │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE   │ FALSE │ TRUE  │
└─────────┴───────┴───────┴───────┴───────┴───────┴───────┴───────┴───────┴───────┴─────────┴───────┴───────┘



运算符==在两种不同类型之间转换,而===运算符则执行“类型安全比较”。 这意味着只有当两个操作数具有相同的类型和相同的值时才会返回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)



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



一张图片胜过千言万语:

PHP双等于==相等图:

PHP三重等于===平等图表:

源代码来创建这些图像:

https://github.com/sentientmachine/php_equality_charts

Guru冥想

那些希望保持清醒的人,不要再读了。

  1. '=='将左右操作数转换为数字(123 ==“123foo”,但是“123”!=“123foo”
  2. 用引号括起来的十六进制字符串有时候是一个浮点数,并且会根据您的意愿进行转换。
  3. ==不是传递的,因为(“0”是== 0,0是==“”,而是“0”!=“”)
  4. “6”==“6”,“4.2”==“4.20”和“133”==“0133”。 但是133!= 0133,因为0133是八进制。 但是“0x10”==“16”和“1e3”==“1000”
  5. 尚未声明的PHP变量是错误的。

  6. False等于0,空白字符串和空数组以及“0”。

  7. 当数字足够大,他们是==无穷大。
  8. NAN本身不==,但它是真的。

  9. 新鲜的类是==到1。

  10. 虚假是最危险的价值,因为虚假是大部分其他变数,大多数是击败它的目的。

希望:

如果你使用PHP,你不应该使用double equals运算符,而总是使用triple equals。




关于对象比较的其他答案除外:

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



最简单的说法是:

==检查是否等价 (只有值)

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


等值对相同:一个类比

1 + 1 = 2 + 0 (等同)

1 + 1 = 1 + 1 (相同)


在PHP中:

true == 1 (true - 等价值)

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

  • true是布尔值
  • 1是int



这完全是关于数据类型的。 以BOOL (true或false)为例:

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 (如果你知道我的意思)。

你为什么需要这个?

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

array_search()函数只是在数组中搜索一个值,并返回找到该值的元素的键。如果在该数组中找不到该值,则返回false 。 但是,如果你对存储在数组第一个元素 (数组键是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。 相反,他们使用! 。 但实际上,这与使用==false是完全一样的,所以如果你这样做:

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

所以对于这样的事情,您可以使用=== ,以便检查数据类型。




一个例子是数据库属性可以是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



给定x = 5

1)运营商:==是“等于”。 x == 8是错误的
2)运算符:===是“完全等于”(值和类型) x === 5是真, x === "5"是假




$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...
}



简而言之,===的工作方式与==在大多数其他编程语言中一样。

PHP允许你进行比较,这是没有意义的。 例:

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

虽然这允许一些有趣的“快捷方式”,你应该小心,因为一个函数返回的东西不应该(如“错误”,而不是一个数字)不会被抓住,你会想知道发生了什么。

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

如果你看一下PHP手册,你会发现很多函数在函数失败的时候返回“false”,但是在成功的情况下可能返回0,这就是为什么他们推荐“if(function()!==假)“以避免错误。




几个例子

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.

PS

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

===比较值和数据类型




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

这不是你想要的。




至于何时使用另一个,例如PHP中的fwrite()函数。

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

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

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

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



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

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

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

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

PHP必须将(“投射”)$ var转换为整数。 在这种情况下,“$ var == 1”是真的,因为任何非空字符串被转换为1。

当使用===时,你检查值AND THE TYPE是否相等,所以“$ var === 1”是false。

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

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

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

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

因为测试是返回值“是一个布尔值并且是假的”而不是“可以被伪造”。




===运算符应该比较确切的内容相等,而==运算符会比较语义相等。 特别是它将强制字符串数字。

平等是一个很大的课题。 请参阅维基百科关于平等的文章




<?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);
?>



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

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

  • “”
  • 空值
  • 0

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




到目前为止,所有的答案都忽略了===的危险问题。 顺便说一下,不过没有强调,integer和double是不同的类型,所以下面的代码:

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

得到:

 equal
 not equal

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

这是一个令人讨厌的问题,因为使用===的程序如果所有数字都足够小(“足够小”取决于所运行的硬件和操作系统),它可以快速运行多年。 然而,偶然的情况下,一个整数恰好足够大,可以被转换为double类型,即使后续的操作或许多操作可能会把它带回到一个小的整数值,它的类型也会被永远地改变。 而且,情况变得更糟。 它可以传播 - 双重感染可以传递到任何接触,一次一个计算。

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

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

所以,在上面的答案有一些不错的表,但没有1(作为一个整数)和1(微妙的双)和1.0(明显的双)之间的区别。 此外,建议你应该总是使用===而不是==不是很好,因为===有时会失败,其中==正常工作。 另外,JavaScript在这方面并不相同,因为它只有一个数字类型(在内部它可能有不同的按位表示,但对===不会造成问题)。

我的建议 - 既不使用。 你需要编写自己的比较函数来解决这个问题。