Чем отличаются операторы сравнения PHP (== double equals) и тождества (=== triple equals)?


509

В чем разница между ==и ===?

  • Как именно работает свободное ==сравнение?
  • Как именно работает строгое ===сравнение?

Какие были бы полезные примеры?

Ответы:


633

Разница между ==и===

Разница между ==оператором со слабым равенством и оператором со строгим ===идентичным идентификатором в точности объяснена в руководстве :

Операторы сравнения

┌──────────┬───────────┬────────────────────────── ─────────────────────────────────┐
│ Пример │ Имя │ Результат │
├──────────┼───────────┼────────────────────────── ─────────────────────────────────┤
A $ a == $ b │ Равен │ ИСТИНА, если $ a равно жонглированию типов. │
A $ a === $ b │ Одинаково │ ИСТИНА, если $ a равно $ b и они одного типа. │
└──────────┴───────────┴────────────────────────── ─────────────────────────────────┘

Слабо ==равное сравнение

Если вы используете ==оператор или любой другой оператор сравнения, который использует слабое сравнение, например !=, <>или ==, вам всегда нужно смотреть на контекст, чтобы увидеть, что, где и почему что-то преобразуется, чтобы понять, что происходит.

Правила конвертации

Таблица сравнения типов

В качестве ссылки и примера вы можете увидеть таблицу сравнения в руководстве :

Слабые сравнения с ==

┌─────────┬───────┬───────┬───────┬───────┬─────── ┬───────┬───────┬───────┬───────┬─────────┬─────── ┬───────┐
│ │ TRUE │ FALSE │ 1 │ 0 │ -1 │ "1" │ "0" │ "-1" │ NULL │ array () │ "php" │ "" │
├─────────┼───────┼───────┼───────┼───────┼─────── ┼───────┼───────┼───────┼───────┼─────────┼─────── ┼───────┤
│ ИСТИНА │ ИСТИНА │ ЛОЖЬ │ ИСТИНА │ ЛОЖЬ │ ИСТИНА │ ИСТИНА │ ЛОЖЬ │ ИСТИНА │ ЛОЖЬ │ ЛОЖЬ │ ИСТИНА │ ЛОЖЬ │
│ ЛОЖЬ │ ЛОЖЬ │ ИСТИНА │ ЛОЖЬ │ ИСТИНА │ ЛОЖЬ │ ЛОЖЬ │ ИСТИНА │ ЛОЖЬ │ ИСТИНА │ ЛОЖЬ │ ИСТИНА │
│ 1 │ ИСТИНА │ ЛОЖЬ │ ИСТИНА │ ЛОЖЬ │ ЛОЖЬ │ ИСТИНА │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │
│ 0 │ ЛОЖЬ │ ИСТИНА │ ЛОЖЬ │ ИСТИНА │ ЛОЖЬ │ ЛОЖЬ │ ИСТИНА │ ЛОЖЬ │ ИСТИНА │ ЛОЖЬ │ ИСТИНА │ ИСТИНА │
│ -1 │ ИСТИНА, ЛОЖЬ, ЛОЖЬ, ЛОЖЬ, ИСТИНА, ЛОЖЬ, ЛОЖЬ, ИСТИНА, ЛОЖЬ, ЛОЖЬ, ЛОЖЬ, ЛОЖЬ.
│ «1» │ ИСТИНА │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │
│ «0» │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │
-1 «-1» │ ИСТИНА │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │
│ NULL │ FALSE │ TRUE │ FALSE │ TRUE │ FALSE │ FALSE │ FALSE │ FALSE │ TRUE │ TRUE │ TRUE │ TRUE
│ array () │ FALSE │ TRUE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ TRUE │ TRUE │ FALSE │ FALSE │
Ph «php» │ ИСТИНА │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ
│ "" │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ИСТИНА │
└─────────┴───────┴───────┴───────┴───────┴─────── ┴───────┴───────┴───────┴───────┴─────────┴─────── ┴───────┘

Строгое ===одинаковое сравнение

Если вы используете ===оператор или любой другой оператор сравнения, который использует строгое сравнение, такое как !==или ===, то вы всегда можете быть уверены, что типы не будут волшебным образом изменяться, потому что преобразование не будет происходить. Таким образом, при строгом сравнении тип и значение должны совпадать, а не только значение.

Таблица сравнения типов

В качестве ссылки и примера вы можете увидеть таблицу сравнения в руководстве :

Строгое сравнение с ===

┌─────────┬───────┬───────┬───────┬───────┬─────── ┬───────┬───────┬───────┬───────┬─────────┬─────── ┬───────┐
│ │ TRUE │ FALSE │ 1 │ 0 │ -1 │ "1" │ "0" │ "-1" │ NULL │ array () │ "php" │ "" │
├─────────┼───────┼───────┼───────┼───────┼─────── ┼───────┼───────┼───────┼───────┼─────────┼─────── ┼───────┤
│ ИСТИНА │ ИСТИНА │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │
│ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │
│ 1 │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ
│ 0 │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ
│ -1 │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │
│ «1» │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ИСТИНА │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │
│ «0» │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │
-1 «-1» │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │
│ НУЛЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │
│ array () │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │
Ph «php» │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │
│ «» │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ЛОЖЬ │ ИСТИНА │
└─────────┴───────┴───────┴───────┴───────┴─────── ┴───────┴───────┴───────┴───────┴─────────┴─────── ┴───────┘

66
кто-нибудь еще находит странным, что "000" == "0000"?
Nickf

36
Меня всегда удивляет, что false == array () и false == 0, но array ()! = 0, поэтому false == array ()! = / == 0? это странно для меня.
Пим Джагер

4
@Pim ... продолжение: Посмотрите на это так: приведение к BOOL, любое значение должно упасть только на одну из двух сторон, trueили false. Это легко разыграть. Все остальные значения имеют, для всех практических целей, практически неограниченные комбинации. Есть "five" == 5? array(0) == 0? array(0,0,0) == 0? 0.0000000000000000000000000000000000000000000000000001 == array()?
deceze

12
@Raithlin, осторожно с массивом. Тройное равенство дает falseдля разных массивов в javascript, но trueдля PHP, пока их значения равны .
Pacerier

14
@Raithlin, еще много много чего надо. В JavaScript: "000" != "00" , "000" == null, "000" == false, "0x0" == false, array() == 0, false != null, array() != null, false == "0x0", false == "000". В PHP это противоположное поведение: "000" == "00" , "000" != null, "000" != false, "0x0" != false, array() != 0, false == null, array() == null, false != "0x0", false != "000".
Pacerier

239

Оператор == осуществляет приведение между двумя различными типами, если они различаются, а оператор === выполняет «безопасное сравнение типов». Это означает, что он вернет 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)

3
Nitpick: === вернет true, только если оба операнда имеют одинаковый тип, а значения равны =)
gnud

1
@gnud Это именно то, что он показал в примере. Если бы он просто сравнивал типы, его просто называли бы «сравнением типов», не так ли?
Роб Стивенсон-Леггетт

3
После 8-летнего использования PHP вчера я впервые попал в ситуацию, когда мне следовало использовать ===

3
=== true, если они равны и имеют одинаковый тип. == правда, если они равны. ! = true, если они не равны. ! == true, если либо они не равны, либо равны, но не одного типа.
Джереми C

1
Кроме того, использование === немного быстрее, чем ==, поскольку не требуется преобразовывать значение перед проверкой, равно ли оно.
Clauziere

88

Одна картинка стоит тысячи слов:

==График равенства PHP Double Equals :

введите описание изображения здесь

===Диаграмма равенства тройных равных PHP :

введите описание изображения здесь

Исходный код для создания этих изображений:

https://github.com/sentientmachine/php_equality_charts

Медитация Гуру

Те, кто хочет сохранить свое здравомыслие, не читают дальше, потому что ничего из этого не имеет никакого смысла, кроме как сказать, что именно так был разработан фрактал безумия в PHP.

  1. NAN != NANно NAN == true.
  2. ==преобразует левый и правый операнды в числа, если левый номер. Так 123 == "123foo", но"123" != "123foo"
  3. Шестнадцатеричная строка в кавычках иногда является плавающей точкой и будет неожиданно брошена против вашей воли, вызывая ошибку во время выполнения.

  4. ==не является переходным, потому что "0"== 0, 0 == ""но"0" != ""

  5. Переменные PHP, которые еще не были объявлены, являются ложными, хотя в PHP есть способ представления неопределенных переменных, эта функция отключена ==.
  6. "6" == " 6", "4.2" == "4.20"и "133" == "0133"но 133 != 0133. Но "0x10" == "16"и предоставление "1e3" == "1000"этого неожиданного преобразования строки в восьмеричное произойдет как без вашего разрешения, так и с согласия, что приведет к ошибке во время выполнения.

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

  8. Когда числа достаточно велики, они == Бесконечность.

  9. Новый класс == к 1.

  10. Ложь является наиболее опасным значением, потому что Ложь == для большинства других переменных, в основном, в ущерб ее цели.

Надежда:

Если вы используете PHP, вы не должны использовать оператор двойного равенства, потому что если вы используете тройное равенство, единственные крайние случаи, о которых нужно беспокоиться, это NAN и числа настолько близкие к бесконечности, что они приводятся к бесконечности. При двойном равенстве все может быть неожиданностью ==для чего-либо или, или может быть удивлением, брошенным против вашей воли и !=чему-то, чему оно явно должно быть равно

Везде, где вы используете ==PHP, дурно пахнет код из-за 85 ошибок в нем, обнаруживаемых неявными правилами приведения, которые, похоже, разработаны миллионами программистов, программирующих с помощью броуновского движения.


Это действительно хорошая идея (также безопасная) всегда использовать тройные равные?
Чейзи Чаз

3
Да, переходное свойство тройного равенства делает его более безопасным и масштабируемым.
Эрик Лещинский

Как число может быть близко к бесконечности? [взрыв мозговой картинки]
Тим

40

Что касается 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');
}

Upvoted, поскольку это, кажется, точно такая же ситуация для php.
Дэвид говорит восстановить Монику

1
@DavidThomas Это не совсем same.See stackoverflow.com/questions/12598407/...
xdazz

22

Дополнение к другим ответам относительно сравнения объектов:

== сравнивает объекты, используя имя объекта и его значения. Если два объекта имеют одинаковый тип и имеют одинаковые значения членов, $a == $bвыдается значение true.

=== сравнивает внутренний идентификатор объекта из объектов. Даже если члены равны, $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

12

Проще говоря:

== проверяет эквивалентность (только значение)

=== проверяет, совпадает ли (значение && type)


эквивалентно или одинаково: аналогия

1 + 1 = 2 + 0 (эквивалент)

1 + 1 = 1 + 1 (то же самое)


В PHP:

true == 1 (true - эквивалент по значению)

true === 1 (false - не совпадает по значению && type)

  • истина булева
  • 1 является целым

«=== проверяет, совпадает ли (значение && type)», не совсем верно. Два объекта stdClass имеют один и тот же тип объекта (то есть, используя gettype ()), но PHP говорит, что это две разные вещи, если вы используете строгое сравнение. Смотрите это .
MAChitgarha

8

Это все о типах данных. Возьмите BOOL(истина или ложь), например:

trueтакже равно, 1а falseтакже равно0

The ==не заботится о типах данных при сравнении: так что если у вас есть переменная, равная 1 (которая также может быть true):

$var=1;

А затем сравните с ==:

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

Но на $varсамом деле не равно true, не так ли? 1Вместо этого он имеет значение int , которое, в свою очередь, равно true.

С ===помощью проверяются типы данных, чтобы убедиться, что две переменные / объекты / что угодно используют один и тот же тип.

Так что если бы я сделал

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

это условие не будет истинным, как $var !== trueтолько == true(если вы знаете, что я имею в виду).

Зачем вам это нужно?

Просто - давайте посмотрим на одну из функций PHP array_search():

array_search()Функция просто ищет значения в массиве и возвращает ключ элемента значение было найдено. Если значение не может быть найден в массиве, он возвращает ложь . Но что делать , если вы сделали значение array_search()on, хранящееся в первом элементе массива (который будет иметь ключ массива 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)

Таким образом, для таких вещей вы должны использовать ===вместо этого, чтобы проверить тип данных.


8

Одним из примеров является то, что атрибут базы данных может быть нулевым или "":

$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

7

php == - это оператор сравнения, который сравнивает значения переменных. Но === сравнивает значение и тип данных.

Например,

<?php 
  $var1 = 10;
  $var2 = '10';

  if($var1 == $var2) {
    echo 'Variables are equal';
  } else {
    echo 'Variables are not equal';
  }
?>

В этом случае вывод будет «Переменные равны», даже если их типы данных различны.

Но если мы будем использовать === вместо ==, результатом будет «Переменные не равны». Сначала php сравнивает значение переменной, а затем тип данных. Здесь значения одинаковы, но типы данных разные.


6

Данный x = 5

1) Оператор: == "равно". x == 8ложно
2) Оператор: === "точно равно" (значение и тип) x === 5верно, x === "5"ложно


3
$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...
}

3

Короче говоря, === работает так же, как == в большинстве других языков программирования.

PHP позволяет проводить сравнения, которые на самом деле не имеют смысла. Пример:

$y = "wauv";
$x = false;
if ($x == $y)
    ...

Хотя это допускает некоторые интересные «горячие клавиши», вам следует остерегаться, поскольку функция, которая возвращает то, что не должна (например, «ошибка» вместо числа), не будет поймана, и вам будет интересно, что же произошло.

В PHP == сравнивает значения и при необходимости выполняет преобразование типа (например, строка «12343sdfjskfjds» станет «12343» в целочисленном сравнении). === будет сравнивать значение И тип и вернет false, если тип не совпадает.

Если вы заглянете в руководство по PHP, то увидите, что многие функции возвращают «ложь» в случае сбоя функции, но они могут вернуть 0 в успешном сценарии, поэтому они рекомендуют делать «if (function ()! ==» ложно) "чтобы избежать ошибок.


1
Следует отметить, что в дополнение к этим «ярлыкам» известно, что ненормальное поведение оператора == открывает дыры в безопасности, например, на популярном форуме PHP, где можно было установить значение хэша пароля cookie в значение true, обходя проверка if (databasehash == cookiehash).
Дэвид

3

Немного примеров

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

== Сравнивает только значение, он не будет беспокоиться о типах данных

против

=== Сравнивает значения и типы данных


в чем проблема с этим ответом?
Мохит Танвани

2

Вы должны использовать ===, чтобы проверить, является ли функция или переменная ложной, а не просто равной ложной (ноль или пустая строка).

$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, что будет равно ложному в тесте

if ($pos == false)

или

if (!$pos)

это не то, что вы хотите здесь.


2

Что касается того, когда использовать один над другим, возьмем, например, fwrite()функцию в PHP.

Эта функция записывает содержимое в файловый поток. Согласно PHP, « fwrite()возвращает количество записанных байтов или FALSE при ошибке». Если вы хотите проверить, был ли вызов функции успешным, этот метод имеет недостатки:

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

Он может вернуть ноль (и считается успешным), и ваше состояние все еще срабатывает. Правильный путь будет:

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

2

PHP является свободно типизированным языком. Использование оператора двойного равенства позволяет свободно проверять переменную.

Слабая проверка значения позволит некоторым подобным, но не равным, значениям равняться одному и тому же:

  • «»
  • значение NULL
  • ложный
  • 0

Все эти значения будут равны как равные, используя оператор двойного равенства.


1

Переменные имеют тип и значение.

  • $ var = "test" - это строка, содержащая "test"
  • $ var2 = 24 - целое число, значение которого равно 24.

Когда вы используете эти переменные (в PHP), иногда у вас нет хорошего типа. Например, если вы делаете

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

PHP должен конвертировать ("для приведения") $ var в целое число. В этом случае «$ var == 1» имеет значение true, потому что любая непустая строка приводится к 1.

При использовании === вы проверяете, что значение И ТИП равны, поэтому "$ var === 1" равно false.

Это полезно, например, когда у вас есть функция, которая может возвращать false (при ошибке) и 0 (результат):

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

Этот код неверен, как будто myFunction()возвращает 0, он приведен к ложному, и вы, кажется, есть ошибка. Правильный код:

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

потому что тест состоит в том, что возвращаемое значение «является логическим значением и является ложным», а не «может быть приведено к ложному».


Что касается непустых строк, это на самом деле не так. «а» == 0 ИСТИНА.
Ник

1

Предполагается, что ===оператор сравнивает точное равенство содержимого, а ==оператор сравнивает семантическое равенство. В частности, он будет приводить строки к числам.

Равенство - обширный предмет. Смотрите статью в Википедии о равенстве .


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

1

Все ответы до сих пор игнорируют опасную проблему с ===. Попутно было отмечено, но не подчеркнуто, что 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

Обратите внимание, что это НЕ случай «ошибки округления». Два числа в точности равны последнему биту, но имеют разные типы.

Это неприятная проблема, потому что программа, использующая ===, может успешно работать годами, если все числа достаточно малы (где «достаточно мало» зависит от оборудования и ОС, на которой вы работаете). Однако если случайно целое число оказывается достаточно большим, чтобы его можно было преобразовать в двойное, его тип изменяется «навсегда», даже если последующая операция или множество операций может вернуть его к небольшому целому значению. И это становится хуже. Он может распространяться - инфекция двойственности может передаваться всем, к чему она касается, по одному расчету за раз.

В реальном мире это, вероятно, будет проблемой в программах, которые обрабатывают даты после 2038 года, например. В настоящее время метки времени UNIX (количество секунд с 1970-01-01 00:00:00 UTC) потребуют более 32 бит, поэтому их представление «волшебным образом» переключится на удвоение в некоторых системах. Поэтому, если вы вычислите разницу между двумя значениями, у вас может получиться пара секунд, но в виде двойного числа, а не целочисленного результата, полученного в 2017 году.

Я думаю, что это намного хуже, чем преобразования между строками и числами, потому что это неуловимо. Мне легко отслеживать, что такое строка и что такое число, но отслеживать количество бит в числе мне не по силам.

Итак, в приведенных выше ответах есть несколько хороших таблиц, но нет различия между 1 (как целое число) и 1 (тонкое двойное число) и 1.0 (очевидное двойное число). Кроме того, совет, что вы всегда должны использовать === и никогда не ==, не очень хорош, потому что === иногда терпит неудачу, когда == работает должным образом. Кроме того, JavaScript не эквивалентен в этом отношении, потому что он имеет только один тип чисел (внутренне он может иметь разные побитовые представления, но это не вызывает проблем для ===).

Мой совет - не используйте ни один. Вам нужно написать свою собственную функцию сравнения, чтобы действительно исправить этот беспорядок.


0

Есть два различия между ==и=== в 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()в тестах выше.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.