PHP的相等(==双等号)和恒等式(===三重等号)比较运算符有什么不同?

=====之间有什么区别?

  • 松散的==比较究竟是如何工作的?
  • 严格的===比较究竟是如何工作的?

有什么有用的例子吗?

368908 次浏览

=====的区别

松散的==相等操作符和严格的===相同操作符之间的区别在手册中得到了准确的解释:

比较运算符

例子 的名字 结果
$a = $b 平等的 如果在杂耍类型后$a等于$b,则为TRUE。
$a == $b 相同的 如果$a等于$b,且两者类型相同,则为TRUE。
人力资源/ > < / div > <

松散的==相等比较

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

转换规则

类型对照表

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

真正的 1 0 -1 “1”; “0”; “1”; 数组() “php" ““
真正的 真正的 真正的 真正的 真正的 真正的 真正的
真正的 真正的 真正的 真正的 真正的 真正的
1 真正的 真正的 真正的
0 真正的 真正的 真正的 真正的 真正的 真正的
-1 真正的 真正的 真正的
“1”; 真正的 真正的 真正的
“0”; 真正的 真正的 真正的
“1”; 真正的 真正的 真正的
真正的 真正的 真正的 真正的 真正的
数组() 真正的 真正的 真正的
“php" 真正的 真正的 真正的
““ 真正的 真正的 真正的 真正的
< / div > # EYZ1

如果您正在使用===操作符,或任何其他使用严格比较的比较操作符,如!=====,那么您总是可以确保类型不会发生神奇的变化,因为不会发生转换。因此,在严格比较中,类型和值必须相同,而不仅仅是值。

类型对照表

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

===严格比较

真正的 1 0 -1 “1”; “0”; “1”; 数组() “php" ““
真正的 真正的
真正的
1 真正的
0 真正的
-1 真正的
“1”; 真正的
“0”; 真正的
“1”; 真正的
真正的
数组() 真正的
“php" 真正的
““ 真正的

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

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

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

这不是你想要的。

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

变量有类型和值。

  • $var = "test"是一个包含"test"的字符串
  • $var2 = 24是一个整数,其值为24。
当你使用这些变量(在PHP中),有时你没有好的类型。 例如,如果您执行

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

PHP必须将$var转换为整数。在本例中,"$var == 1"为真,因为任何非空字符串都被转换为1。

当使用===时,检查值和类型是否相等,因此"$var === 1"为假。

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

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

这段代码是错误的,如果myFunction()返回0,它被强制转换为false,你似乎有一个错误。正确的代码是:

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

因为测试的是返回值“是一个布尔值并且为假”,而不是“可以被强制转换为假”。

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

关于对象比较的其他答案的补充:

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

这都是关于数据类型的。以BOOL(真或假)为例:

true也等于1false也等于0

==在比较时不关心数据类型: 所以如果你有一个变量是1(也可以是true):

# EYZ0

然后与==进行比较:

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()函数只是在数组中搜索一个值,并返回找到该值的元素的键。如果在数组中找不到该值,则返回。但是,如果对存储在数组的第一个元素(数组键为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完全相同,所以如果你这样做:

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

因此,对于这样的事情,您将使用===代替,以便检查数据类型。

<?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 Double Equals ==相等图表:

enter image description here

PHP三重相等===相等图表:

enter image description here

创建这些图像的源代码:

https://github.com/sentientmachine/php_equality_charts

大师冥想

那些希望保持理智的人,不要再读下去了,因为这些都没有任何意义,只能说PHP的疯狂分形就是这样设计的。

  1. NAN != NANNAN == true

  2. ==将左、右操作数转换为数字(如果左为数字)。所以是123 == "123foo",但是是"123" != "123foo"

  3. 引号中的十六进制字符串偶尔是浮点数,并且会被强制转换为违背您的意愿的浮点数,从而导致运行时错误。

  4. ==是不可传递的,因为"0"== 00 == """0" != ""

  5. 尚未声明的变量为false,尽管PHP有一种表示未定义变量的方法,但该功能在==中被禁用。

  6. "6" == " 6""4.2" == "4.20""133" == "0133"但是133 != 0133。但是"0x10" == "16""1e3" == "1000"会在没有您的指令或同意的情况下将意外的字符串转换为八进制,从而导致运行时错误。

  7. False == 0""[]"0"

  8. 如果你给number加上1并且它们已经保持了它们的最大值,它们不会被换行,而是被强制转换为infinity

  9. 一个新类==到1。

  10. False是最危险的值,因为False对于大多数其他变量都是==,大多数情况下都违背了它的目的。

希望:

如果你正在使用PHP,你不应该使用双等号操作符,因为如果你使用三等号,唯一需要担心的边缘情况是NAN和太接近其数据类型最大值的数字,它们会被强制转换为无穷大。使用双等号,任何东西都可以是出乎意料的==或任何东西,或可以是出乎意料的施加违背你的意愿和!=显然应该是相等的东西。

在PHP中使用==的任何地方都是一股糟糕的代码味道,因为它暴露了85个漏洞,这些漏洞似乎是由数百万程序员根据布朗运动编程设计的隐式强制转换规则暴露出来的。

到目前为止,所有的答案都忽略了一个危险的问题===。这里已经顺便提过,但没有强调,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在这方面是不等效的,因为它只有一种数字类型(在内部它可能有不同的位表示,但它不会导致===的问题)。

我的建议是——两者都不要用。你需要编写自己的比较函数来解决这个问题。

在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

请注意:将一个对象赋值给另一个变量并不会创建一个副本——相反,它会创建一个对同一对象的引用。# EYZ1。

请注意:在PHP7中引入了匿名类。在上面的测试中,new class {}new stdClass()之间没有区别。

PHP Double = ==:

在大多数编程语言中,比较操作符(==)一方面检查数据类型,另一方面检查变量的内容是否相等。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提供了两个比较运算符来检查两个值是否相等。这两者之间的主要区别是'=='检查两个操作数的值是否为equal or not。另一方面,'==='检查值以及操作数的类型是equal or not

= =(等于)

===(完全相等)

示例=比;

<?php
$val1 = 1234;
$val2 = "1234";
var_dump($val1 == $val2);// output => bool(true)
//It checks only operands value
?>




<?php
$val1 = 1234;
$val2 = "1234";
var_dump($val1 === $val2);// output => bool(false)
//First it checks type then operands value
?>

如果将$val2转换为(int)$val2或(string)$val1,则返回true

   <?php
$val1 = 1234;
$val2 = "1234";
var_dump($val1 === (int)$val2);// output => bool(true)
//First it checks type then operands value
?>

  <?php
$val1 = 1234;
$val2 = "1234";
var_dump($val1 === (int)$val2);// output => bool(true)
//First it checks type then operands value
?>