Answers:
==
和之间的区别===
松散之间的差==
等于操作员和严格===
相同的运算符中被精确地说明手册:
比较运算符
──────────┬──────────┬──────────────────── ──────────────────┐ │示例│名称│结果│ ├──────────┼──────────┼──────────────────── ──────────────────┤ │$ a == $ b│等于│真,如果类型变戏后$ a等于$ b。│ │$ a === $ b│相同│如果$ a等于$ b并且它们是同一类型,则为TRUE。│ ──────────┴──────────┴──────────────────── ──────────────────┘
==
相等的比较如果您使用的是==
运营商,或者松散的使用相比其他运营商相比,诸如!=
,<>
或者==
,你总是要看看上下文看什么,在哪里,为什么得到的东西转化为理解是怎么回事。
作为参考和示例,您可以在手册中看到比较表:
松散的比较
==
──────────┬───────┬──────┬──────┬──────┬ ────────┬────────┬──────────────┬──────┬ ┬────────┐ ││TRUE│FALSE│1│0│-1│“ 1”│“ 0”│“ -1”│NULL│array()│“ php”│“”│ ├──────────┼──────┼────────┼──────┼──────┼ ────────┼────────┼──────────────┼──────┼ ┼──────┤ │真│真│假│真│假│真│真│假│真│假│假│真│假│假│ │假│假│真│假│真│假│假│真│假│真│真│假│真│ │1│真│假│真│假│假│真│假│假│假│假│假│假│ │0│假│真│假│真│假│假│真│假│真│假│真│真│ │-1│真│假│假│假│真│假│假│真│假│假│假│假│假│ │“ 1”│真│假│真│假│假│真│假│假│假│假│假│假│假│ │“ 0”│假│是│假│真│假│假│真│假│假│假│假│假│假│ │“ -1”│是│假│假│假│真│假│假│真│假│假│假│假│假│ │空│假│真│假│真│假│假│假│假│真│真│假│真│ │数组()│假│是│假│假│假│假│假│假│假│真│真│假│假│假│ │“ php”│TRUE│FALSE│FALSE│TRUE│FALSE│FALSE│FALSE│FALSE│FALSE│FALSE│TRUE│FALSE│ │“”│假│真│假│真│假│假│假│假│假│真│假│假│真│ ──────────┴───────┴──────┴──────┴──────┴ ────────┴────────┴──────────────┴──────┴ ┴──────┘
===
相同的比较如果您使用的是===
运算符,或者使用严格比较的任何其他比较运算符(例如!==
或)===
,那么您始终可以确保类型不会发生神奇的变化,因为不会进行任何转换。因此,通过严格比较,类型和值必须相同,而不仅是值。
作为参考和示例,您可以在手册中看到比较表:
严格比较
===
──────────┬───────┬──────┬──────┬──────┬ ────────┬────────┬──────────────┬──────┬ ┬────────┐ ││TRUE│FALSE│1│0│-1│“ 1”│“ 0”│“ -1”│NULL│array()│“ php”│“”│ ├──────────┼──────┼────────┼──────┼──────┼ ────────┼────────┼──────────────┼──────┼ ┼──────┤ │真│真│假│假│假│假│假│假│假│假│假│假│假│假│假│ │假│假│真│假│假│假│假│假│假│假│假│假│假│假│假│ │1│假│假│真│假│假│假│假│假│假│假│假│假│假│ │0│假│假│假│真│假│假│假│假│假│假│假│假│假│假│ │-1│假│假│假│假│真│假│假│假│假│假│假│假│假│ │“ 1”│假│假│假│假│假│真│假│假│假│假│假│假│假│ │“ 0”│假│假│假│假│假│假│真TRUE│假│假│假│假│假│假│ │“ -1”│假│假│假│假│假│假│假│假│真│假│假│假│假│假│ │空│假│假│假│假│假│假│假│假│假│真│假│假│假│假│ │数组()│假│假│假│假│假│假│假│假│假│假│真│假│假│假│ │“ php”│假│假│假│假│假│假│假│假│假│假│假│真│假│假│ │“”│假│假│假│假│假│假│假│假│假│假│假│假│假│正确│ ──────────┴───────┴──────┴──────┴──────┴ ────────┴────────┴──────────────┴──────┴ ┴──────┘
true
或上false
。这很容易投射。对于所有实际目的,所有其他值实际上具有无限的组合。是"five" == 5
吗 array(0) == 0
?array(0,0,0) == 0
?0.0000000000000000000000000000000000000000000000000001 == array()
?
false
在javascript中提供了不同的数组,但true
在PHP中,只要它们的值相等即可。
"000" != "00"
,"000" == null
,"000" == false
,"0x0" == false
,array() == 0
,false != null
,array() != null
,。false == "0x0"
在PHP中,这是相反的行为:,,,,,,,,。false == "000"
"000" == "00"
"000" != null
"000" != false
"0x0" != false
array() != 0
false == null
array() == null
false != "0x0"
false != "000"
如果==运算符不同,则它们在两种不同类型之间进行转换,而===运算符执行“类型安全比较”。这意味着只有两个操作数具有相同的类型和相同的值时,它才返回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)
一张图片胜过千言万语:
==
相等图:===
相等相等图表:创建这些图像的源代码:
https://github.com/sentientmachine/php_equality_charts
那些希望保持理智的人不再阅读,因为这无济于事,只能说这是PHP的疯狂分形的设计方式。
NAN != NAN
但是NAN == true
。 ==
如果left是数字,则会将左右操作数转换为数字。所以123 == "123foo"
,但是"123" != "123foo"
引号中的十六进制字符串有时是浮点数,并且会意外地根据您的意愿进行浮点数转换,从而导致运行时错误。
==
是不是因为传递"0"== 0
,和0 == ""
而"0" != ""
==
。"6" == " 6"
,"4.2" == "4.20"
和"133" == "0133"
但133 != 0133
。但是"0x10" == "16"
,"1e3" == "1000"
在没有您的指令或同意的情况下,将意外的字符串转换为八进制都会发生,从而导致运行时错误。
False == 0
,""
,[]
和"0"
。
当数字足够大时,它们就是==无穷大。
一个新鲜的类是==到1。
如果您使用的是PHP,则不要使用double equals运算符,因为如果使用Triple equals,则唯一需要担心的情况是NAN和数字非常接近无穷大以至于它们被强制转换为无穷大。使用双重等于,任何事情都可能使任何事情感到惊讶==
,或者使您的意志和!=
显然应当相等的事情感到惊讶。
==
在PHP中使用的任何地方都会有不好的代码味道,因为其中隐含的转换规则暴露了其中的85个错误,这些隐含的转换规则似乎是由数百万程序员通过布朗运动编程的。
关于对象比较的其他答案的补充:
==使用对象名称及其值比较对象。如果两个对象具有相同的类型并具有相同的成员值,则$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-值&&类型不同)
这都是关于数据类型的。以BOOL
(正确或错误)为例:
true
也等于1
和
false
也等于0
该==
不关心比较时的数据类型:所以,如果你有一个变量,它是1(这也可能是true
):
$var=1;
然后与==
:
if ($var == true)
{
echo"var is true";
}
但$var
实际上并不等于true
吗?它具有int值,1
而int值等于true。
用 ===
,检查数据类型,以确保两个变量/对象/所有变量都使用相同的类型。
所以如果我做到了
if ($var === true)
{
echo "var is true";
}
该条件将不成立,因为 $var !== true
仅是== true
(如果您知道我的意思)。
你为什么需要这个?
简单-让我们看一下PHP的功能之一: array_search()
:
该array_search()
函数仅在数组中搜索值,然后返回在其中找到该值的元素的键。如果在数组中找不到该值,则返回false。但是,如果array_search()
对存储在数组第一个元素(其数组键为0
)中的值进行了...处理,该怎么办?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)
因此对于类似的事情,您将使用===
代替,以便检查数据类型。
一个示例是数据库属性可以为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
$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.
聚苯乙烯
==仅比较值,不会理会数据类型
与
===比较值和数据类型
您将使用===来测试函数或变量是否为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中)时,有时您没有好的类型。例如,如果您这样做
if ($var == 1) {... do something ...}
PHP必须将$ var转换(“强制转换”)为整数。在这种情况下,“ $ var == 1”为true,因为任何非空字符串都将强制转换为1。
使用===时,请检查值和THE TYPE是否相等,因此“ $ var === 1”为false。
例如,当您有一个可以返回false(错误)和0(结果)的函数时,这很有用:
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);
?>
到目前为止,所有答案都忽略了===的危险问题。顺便指出,但没有强调,整数和双精度类型是不同的类型,因此以下代码:
$n = 1000;
$d = $n + 0.0e0;
echo '<br/>'. ( ($n == $d)?'equal' :'not equal' );
echo '<br/>'. ( ($n === $d)?'equal' :'not equal' );
给出:
equal
not equal
注意,这不是“舍入错误”的情况。这两个数字直到最后一位完全相等,但是它们的类型不同。
这是一个令人讨厌的问题,因为如果所有数字都足够小(其中“足够小”取决于您所运行的硬件和操作系统),则使用===的程序可以愉快地运行数年。但是,如果偶然地一个整数恰巧足够大以至可以转换为双精度数,即使后续操作或许多操作可能会将其恢复为较小的整数值,其类型也会“永久”更改。而且,情况变得更糟。它可以传播-双重感染可以传给它接触的任何事物,一次计算一次。
例如,在现实世界中,这可能会在处理日期超过2038年的程序中成为问题。此时,UNIX时间戳(自1970-01-01 00:00:00 UTC开始的秒数)将需要超过32位,因此在某些系统上,它们的表示形式将“神奇地”切换为两倍。因此,如果您计算两次之间的差额,则可能会花费几秒钟,但会变成两倍,而不是2017年的整数结果。
我认为这比字符串和数字之间的转换要差得多,因为它很微妙。我发现跟踪一个字符串和一个数字很容易,但是跟踪数字中的位数并不容易。
因此,在上面的答案中,有一些不错的表,但1(作为整数)与1(微妙的双精度)和1.0(明显的双精度)之间没有区别。另外,建议您始终使用===且永远不要使用==并不是很好,因为===有时会在==正常工作的地方失败。同样,JavaScript在这方面也不等效,因为它只有一种数字类型(内部可能具有不同的按位表示,但对于===不会造成问题)。
我的建议-都不使用。您需要编写自己的比较函数才能真正解决此问题。
==
和之间有两个区别===
在PHP数组和对象,我认为这里没有提到。具有不同键排序和对象的两个数组。
如果您有一个具有键排序的数组和另一个具有不同键排序的数组,则它们是严格不同的(即使用===
)。如果对数组进行键排序,然后尝试将排序后的数组与原始数组进行比较,则可能会导致这种情况。
例如,考虑一个空数组。首先,我们尝试将一些新索引推入数组,而不进行任何特殊排序。一个很好的例子是一个以字符串为键的数组。现在深入一个例子:
// Define an array
$arr = [];
// Adding unsorted keys
$arr["I"] = "we";
$arr["you"] = "you";
$arr["he"] = "they";
现在,我们有了一个未排序的键数组(例如,“他”在“您”之后)。考虑相同的数组,但是我们按字母顺序对键进行排序:
// Declare array
$alphabetArr = [];
// Adding alphabetical-sorted keys
$alphabetArr["I"] = "we";
$alphabetArr["he"] = "they";
$alphabetArr["you"] = "you";
小费:您可以使用ksort()按键对数组进行排序函数。
现在,您有了另一个数组,该数组的键排序与第一个数组不同。因此,我们将对其进行比较:
$arr == $alphabetArr; // true
$arr === $alphabetArr; // false
注意:这也许很明显,但是比较两个不同始终使用严格比较来数组false
。但是,两个任意数组的使用===
与否可能相等。
您会说:“这种差异可以忽略不计”。然后我说这是有区别的,应该考虑并可能随时发生。如上所述,对数组中的键进行排序就是一个很好的例子。
请记住,两个不同的对象从不严格相等。这些示例将有助于:
$stdClass1 = new stdClass();
$stdClass2 = new stdClass();
$clonedStdClass1 = clone $stdClass1;
// Comparing
$stdClass1 == $stdClass2; // true
$stdClass1 === $stdClass2; // false
$stdClass1 == $clonedStdClass1; // true
$stdClass1 === $clonedStdClass1; // false
注意:将对象分配给另一个变量不会创建副本,而是会创建对与该对象相同的内存位置的引用。看这里。
注意:从PHP7开始,添加了匿名类。从结果来看,有没有什么区别new class {}
,并new stdClass()
在上面的测试。