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在這方面並不相同,因為它只有一個數字類型(在內部它可能有不同的按位表示,但對===不會造成問題)。

我的建議 - 既不使用。 你需要編寫自己的比較函數來解決這個問題。