==和===的区别是什么?

松==比较究竟是如何工作的? 严格的===比较到底是如何工作的?

有什么有用的例子吗?


当前回答

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中==和===的区别

其他回答

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

==和===的差值

松散==相等操作符和严格===相同操作符之间的区别在手册中有详细解释:

比较运算符

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.

松散==相等比较

如果您正在使用==操作符,或任何其他使用松散比较的比较操作符,如!=,<>或==,您总是必须查看上下文,以了解转换的内容,位置和原因,以了解发生了什么。

转换规则

转换为布尔值 转换为整数 转换为浮点数 转换为字符串 转换为数组 转换为对象 转换为资源 转换为NULL

类型对照表

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

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

编者注-这是正确的引用之前,但更可读作为降价表。这不是抄袭

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中==和===的区别

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

$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)

or

if (!$pos)

这不是你想要的。

在PHP数组和对象中,==和===之间有两个没有人提到的区别:两个具有不同键排序的数组和对象。

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

如果你有两个数组,它们的键排序不同,但有相同的键值映射,它们是严格不同的(即使用===)。这可能会导致问题,如果你对一个数组进行键排序,并试图将排序后的数组与原始数组进行比较。

例如:

$arrayUnsorted = [
    "you" => "you",
    "I" => "we",
];

$arraySorted = $arrayUnsorted;
ksort($arraySorted);

$arrayUnsorted == $arraySorted; // true
$arrayUnsorted === $arraySorted; // false

对象

请记住,主要规则是两个不同的对象永远不会严格相等。请看下面的例子:

$stdClass1 = new stdClass();
$stdClass2 = new stdClass();
$clonedStdClass1 = clone $stdClass1;

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

注意:将一个对象赋值给另一个变量并不会创建一个副本——相反,它创建了对同一对象的引用。在这里看到的。

注意:从PHP7开始,引入了匿名类。在上面的测试中,新类{}和新stdClass()之间没有区别。