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

=====什么区别?

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

什么是一些有用的例子?

=====之间的区别

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

比较运算符

 ┌──────────┬───────────┬────────────────────────── ─────────────────────────────────┐
 │例子│名字│结果│
 ├──────────┼───────────┼────────────────────────── ─────────────────────────────────┤
 │$ a == $ b│等于│如果$ a等于$ b后types变为TRUE。  │
 │$ a === $ b│相同的│如果$ a等于$ b,则它们是相同的types。  │
 └──────────┴───────────┴────────────────────────── ─────────────────────────────────┘

松散==相等的比较

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

转换规则

  • 转换为布尔值
  • 转换为整数
  • 转换为浮动
  • 转换为string
  • 转换为数组
  • 转换为对象
  • 转换为资源
  • 转换为NULL

types比较表

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

==进行比较

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

严格===相同的比较

如果您正在使用===运算符或任何其他使用严格比较(例如!=====比较运算符,那么您始终可以确定这些types不会奇迹般地更改,因为不会有任何转换继续。 所以经过严格比较,types和价值必须相同,而不仅仅是价值。

types比较表

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

严格与===比较

  ┌─────────┬───────┬───────┬───────┬───────┬─────── ┬───────┬───────┬───────┬───────┬─────────┬─────── ┬───────┐
 │││TRUE│FALSE│1│0│-1│“1”│“0”│“-1”│NULL│array()│“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│错误│错误│错误│TRUE│错误│错误│错误│错误│错误│错误│错误│错误│
 │-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│
 │“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│
 │array()│FALSE│FALSE│FALSE│FALSE│FALSE│FALSE│FALSE│FALSE│FALSE│TRUE│FALSE│FALSE│
 │“php”│错误│错误│错误│错误│错误│错误│错误│错误│错误│错误│真值│错误│
 │“”│假│假│假│假│假│假│假
 └─────────┴───────┴───────┴───────┴───────┴─────── ┴───────┴───────┴───────┴───────┴─────────┴─────── ┴───────┘

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

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

例如,下面的示例将显示“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三重等于===平等图表:

在这里输入图像描述

源代码来创build这些图像:

https://github.com/sentientmachine/php_equality_charts

Guru冥想

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

  1. '=='将左右操作数转换为数字(123 ==“123foo”,但是“123”!=“123foo”
  2. 引号中的hexstring偶尔会是一个浮点数,并且会被违背您的意愿进行转换。
  3. ==不是传递的,因为(“0”是== 0,0是==“”,而是“0”!=“”)
  4. “6”==“6”,“4.2”==“4.20”和“133”==“0133”。 但是133!= 0133,因为0133是八进制。 但是“0x10”==“16”和“1e3”==“1000”
  5. 尚未声明的PHPvariables是错误的。

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

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

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

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

希望:

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

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

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

最简单的说法是:

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

===检查是否相同 (值&&types)

等值对相同:一个类比

1 + 1 = 2 + 0 (等同)

1 + 1 = 1 + 1 (相同)

在PHP中:

true == 1 (true – 等价值)

true === 1 (false – 值&&types不一样)

  • true是布尔值
  • 1是int

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

true也等于1false也等于0

在比较时, ==不关心数据types:所以如果你有一个variables是1(这也可能是true ):

$var=1;

然后再比较==

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

$var实际上并不等于true ,是吗? 它的int值是1而这又等于true。

=== ,检查数据types以确保两个variables/对象/任何使用相同的types。

所以,如果我做到了

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

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

你为什么需要这个?

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

array_search()函数只是在数组中search一个值,并返回find该值的元素的键。如果在数组中找不到该值,则返回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) 

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

一个例子是数据库属性可以是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)运算符:===是“完全等于”(值和types) 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中,==比较值并在必要时执行types转换(例如,string“12343sdfjskfjds”将在整数比较中变为“12343”)。 ===将比较值ANDtypes,如果types不相同,将返回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

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

===比较值和数据types

您可以使用===来testing函数或variables是否为false,而不是等于false(零或空string)。

 $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,这在testing中将等于false

 if ($pos == false) 

要么

 if (!$pos) 

这不是你想要的。

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

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

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

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

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

variables有一个types和一个值。

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

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

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

PHP必须将(“投射”)$ var转换为整数。 在这种情况下,“$ var == 1”是真的,因为任何非空string被转换为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 ... } 

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

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

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

 <?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是一种松散types的语言。 使用双等号运算符可以对variables进行松散的检查。

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

  • “”
  • 空值
  • 0

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

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

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

得到:

  equal not equal 

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

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

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

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

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

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