Як відрізняються оператори порівняння рівності PHP (== подвійні рівні) та тотожності (=== потрійні рівні)?


Відповіді:


633

Різниця між ==і===

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

Оператори порівняння

┌─────────────────────────────────────────────────── ──────────────────────────────────┐
│ Приклад │ Ім'я │ Результат │
├─────────────────────────────────────────────────── ──────────────────────────────────┤
│ $ a == $ b │ Дорівнює │ ІСТИНА, якщо $ a дорівнює $ b після типу жонглювання. │
│ $ a === $ b │ Ідентична │ ІСТИНА, якщо $ a дорівнює $ b, і вони одного типу. │
└─────────────────────────────────────────────────── ──────────────────────────────────┘

Слабо ==рівне порівняння

Якщо ви використовуєте ==оператора або будь-якого іншого оператора порівняння, який використовує слабке порівняння, наприклад !=, <>або ==, вам завжди потрібно подивитися на контекст, щоб побачити, що, де і чому щось перетворюється, щоб зрозуміти, що відбувається.

Правила перетворення

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

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

Вільні порівняння з ==

┌─────────────────────────────────────────────────── ┬─────────────────────────────────────────────────── ┬───────┐
│ │ ІСТИНА │ FALSE │ 1 │ 0 │ -1 │ "1" │ "0" │ "-1" │ NULL │ масив () │ "php" │ "" │
├─────────────────────────────────────────────────── ┼─────────────────────────────────────────────────── ┼───────┤
│ ІСТИНА │ ІСТИНА │ ФАЛЬСА │ ІСТИНА │ ФАЛЬСА │ ПРАВДА │ ІСТИНА AL ФАЛЬСЬКА │ ІСТИНА AL ФАЛЬСА AL ЛАЖКА UE ІСТИНА AL ФАЛЬС │
│ ФАЛЬСЬКА │ ЛУЖКА │ ПРАВДА │ ФАЛЬСА │ ІСТИНА │ ФАЛЬСА │ ЛАСКА SE ІСТИНА │ ФАЛЬСА │ ПРАВДА │ ІСТИНА │ ФАЛЬС │ ПРАВИЛЬНА │
│ 1 │ ІСТИНА │ FALSE │ ІСТИНА │ FALSE │ FALSE │ ІСТИНА │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │
│ 0 │ FALSE │ TRUE │ FALSE │ TRUE │ FALSE │ FALSE │ TRUE │ FALSE │ TRUE │ FALSE │ TRUE │ TRUE │
│ -1 │ ПРАВИЛЬНА │ ЛАЖКА │ ФАЛЬСА │ ФАЛЬСА │ ПРАВДА │ ФАЛЬСА │ ФАЛЬСЬКА │ ПРАВИНА AL ФАЛЬСА AL ФАЛЬСЕ AL ФАЛЬСА │ ЛАСКА │
│ "1" │ ПРАВИЛЬНА │ FALSE │ ІСТИНА │ FALSE │ FALSE │ ІСТИНА │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │
│ "0" │ ЛЕЖКА │ ІСТИНА │ ЛАЖКА │ ІСТИНА │ ФАЛЬСА AL ФАЛЬСА │ ПРАВИНА │ ФАЛЬ │ ФАЛЬ │ ФАЛЬС │ ФАЛЬС │ ФАЛЬ │
│ "-1" │ ІСТИНА │ FALSE AL FALSE │ FALSE │ ІСТИНА │ FALSE │ FALSE │ ІСТИНА │ FALSE │ FALSE │ FALSE │ FALSE │
│ NULL │ FALSE │ ІСТИНА │ FALSE │ TRUE │ FALSE │ FALSE │ FALSE │ FALSE │ TRUE │ TRUE │ FALSE │ TRUE │
│ масив () │ ФАЛЬ │ ІСТИНА │ ФАЛЬ │ ФАЛЬ │ ФАЛЬС │ ФАЛЬС │ ФАЛЬ │ ФАЛЬ │ ІСТИНА │ ПРАВИЛЬНА SE ФАЛЬС │ ФАЛЬС │
│ "php" │ ПРАВИЛЬНА │ ЛАЖКА │ ФАЛЬСА │ ПРАВИЛЬНА │ ЛОЖКА │ ФАЛЬСА SE ФАЛЬСА SE ФАЛЬСА SE ФАЛЬСА SE ФАЛЬСА │ ПРАВИЛЬНА │ ФАЛЬСА │
│ "" │ FALSE │ ІСТИНА │ FALSE │ ІСТИНА │ FALSE │ FALSE │ FALSE │ FALSE │ ІСТИНА │ FALSE │ FALSE │ TRUE │
└─────────────────────────────────────────────────── ┴─────────────────────────────────────────────────── ┴───────┘

Суворе ===однакове порівняння

Якщо ви використовуєте ===оператора або будь-якого іншого оператора порівняння, який використовує суворе порівняння, наприклад, !==або ===, ви завжди можете бути впевнені, що типи не будуть магічно змінюватися, оскільки перетворення не буде відбуватися. Тож при суворому порівнянні тип і значення повинні бути однаковими, а не тільки значеннями.

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

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

Суворе порівняння з ===

┌─────────────────────────────────────────────────── ┬─────────────────────────────────────────────────── ┬───────┐
│ │ ІСТИНА │ FALSE │ 1 │ 0 │ -1 │ "1" │ "0" │ "-1" │ NULL │ масив () │ "php" │ "" │
├─────────────────────────────────────────────────── ┼─────────────────────────────────────────────────── ┼───────┤
│ ІСТИНА │ ПРАВИЛЬНА │ ЛАЖКА │ ФАЛЬСА │ ФАЛЬ │ ФАЛЬСА │ ФАЛЬСА │ ФАЛЬ │ ФАЛЬ │ ФАЛЬ │ ФАЛЬС │ ФАЛЬ │ ФАЛЬС │
│ ФАЛЬСЬКА │ ЛАЖКА │ ПРАВИЛЬНА │ ФАЛЬСА │ ФАЛЬСА │ ФАЛЬСА AL ФАЛЬСЬКА │ ФАЛЬСА │ ФАЛЬ │ ФАЛЬСА │ ФАЛЬСА │ ФАЛЬ │ ФАЛЬЗА │
│ 1 │ FALSE │ FALSE │ ІСТИНА │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE AL FALSE │ FALSE │ FALSE │
│ 0 │ FALSE │ FALSE │ FALSE │ TRUE │ FALSE │ FALSE AL FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │
│ -1 │ FALSE │ FALSE │ FALSE │ FALSE │ ІСТИНА │ FALSE AL FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │
│ "1" │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ ІСТИНА │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │
│ "0" │ FALSE │ FALSE AL FALSE │ FALSE │ FALSE │ FALSE │ TRUE │ FALSE │ FALSE AL FALSE │ FALSE │ FALSE │
│ "-1" │ FALSE │ FALSE AL FALSE │ FALSE │ FALSE AL FALSE │ FALSE │ TRUE │ FALSE AL FALSE │ FALSE │ FALSE │
│ NULL │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ TRUE │ FALSE SE FALSE SE FALSE │
│ масив () │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ TRUE │ FALSE │ FALSE │
│ "php" │ FALSE │ FALSE AL FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE AL FALSE │ FALSE │ TRUE │ FALSE │
│ "" │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE AL FALSE │ FALSE UE TRUE │
└─────────────────────────────────────────────────── ┴─────────────────────────────────────────────────── ┴───────┘

65
комусь ще здається дивним, що "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()?
деге

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".
Пейсьєр

239

Оператор == кидає між двома різними типами, якщо вони різні, в той час як оператор === виконує "порівняння безпечного типу". Це означає, що він поверне справжній лише тоді, коли обидва операнди мають один і той же тип і однакове значення.

Приклади:

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: === поверне істину лише у тому випадку, якщо обидва операнди одного типу та значення рівні =)
gnud

1
@gnud Це саме те, що він показав у прикладі. Якби це було лише порівняння типів, це було б просто назване "порівняння типів", чи не так.
Роб Стівенсон-Леггетт

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

3
=== вірно, якщо вони рівні та мають один і той же тип. == вірно, якщо вони рівні. ! = вірно, якщо вони не рівні. ! == вірно, якщо вони не рівні, або рівні, але не одного типу.
Джеремі C

1
Також використання === трохи швидше, ніж ==, оскільки не потрібно перетворювати значення, перш ніж перевіряти, чи воно рівне.
clauziere

88

Малюнок вартує тисячі слів:

PHP подвійний дорівнює ==діаграмі рівності:

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

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. False - це найнебезпечніше значення, оскільки False є == для більшості інших змінних, переважно перемагаючи його мету.

Надія:

Якщо ви використовуєте PHP, не використовуйте оператора подвійних рівних, тому що якщо ви використовуєте потрійні рівні, єдині кращі випадки, про які слід турбуватися, - це NAN та числа, настільки близькі до нескінченності, що вони передаються до нескінченності. При подвійних рівних будь-що може здивувати ==будь-що або, або може бути здивовано, подане проти вашої волі та!= чимось, з чого воно, очевидно, повинно бути рівним.

Де б ви не використовували ==в PHP - це поганий запах коду через 85 помилок у ньому, які піддаються неявним правилам кастингу, які, здається, розроблені мільйонами програмістів, програмуючих броунівським рухом.


Дійсно (також безпечно) завжди використовувати потрійні рівні?
Chazy Chaz

3
Так, перехідна властивість потрійних рівних робить її більш захищеною та низькою.
Ерік Лещинський

Як число може бути близьким до нескінченності? [вибухає мозковий gif]
Тім

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

Оновлено, оскільки це, здається, абсолютно однакова ситуація для php.
Девід каже повернути Моніку

1
@DavidThomas Це не зовсім same.See stackoverflow.com/questions/12598407 / ...
xdazz

22

Додаток до інших відповідей щодо порівняння об'єктів:

== порівнює об’єкти, використовуючи назву об'єкта та їх значення. Якщо два об'єкти одного типу і мають однакові значення членів, $a == $bвиходить істина.

=== порівнює внутрішній ідентифікатор об'єкта. Навіть якщо члени рівні, $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

Простіше кажучи:

== перевіряє, чи еквівалентний (лише значення)

=== перевіряє, чи однаковий (значення & тип)


еквівалентний порівняно з тим же: Аналогія

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

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


У PHP:

true == 1 (вірно - еквівалент у значенні)

true === 1 (false - не однакове значення & type)

  • правда булева
  • 1 - int

"=== перевіряє, чи однакове (значення & тип)", не зовсім вірно. Два об’єкти stdClass мають один і той же тип 'об’єкта' (тобто, використовуючи gettype ()), але PHP каже, що це дві різні речі, якщо ви використовуєте суворе порівняння. Дивіться це .
MAChitgarha

8

Це все про типи даних. Візьмемо BOOLдля прикладу (істинне чи помилкове):

trueтакож дорівнює 1і falseтакож дорівнює0

==Чи не піклується про типах даних при порівнянні: Так що, якщо ви мали змінну , яка є 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()значення, яке зберігалося в першому елементі масиву (який мав би ключ масиву 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...
}

vs.

// 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" у цілому порівнянні). === порівняє значення AND type та поверне false, якщо тип не є однаковим.

Якщо ви подивитесь в посібник з PHP, ви побачите, що багато функцій повертаються "помилково", якщо функція не працює, але вони можуть повернути 0 в успішному сценарії, тому рекомендують робити "if (function ()! == помилково) "щоб уникнути помилок.


1
Слід зазначити, що крім цих "ярликів", аномальне поведінка оператора ==, як відомо, відкриває захисні отвори, наприклад, популярний форум PHP, де можна було встановити значення хеша для паролів cookie на істинне, обходячи його перевірка 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

== Порівнюючи лише значення, воно не турбуватиметься про типи даних

vs.

=== Порівняє значення та типи даних


в чому проблема з цією відповіддю?
Мохіт Танвані

2

Ви б використовували === для перевірки того, чи є функція чи змінна помилковою, а не просто прирівнюється до 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, що прирівнюється до хибного в тесті

if ($pos == false)

або

if (!$pos)

що тут не те, що ви хочете.


2

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

Ця функція записує вміст у файловий потік. Згідно з PHP, " fwrite()повертає кількість записаних байтів, або FALSE на помилку." Якщо ви хочете перевірити, чи функціональний виклик був успішним, цей метод має помилку:

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

Він може повернути нуль (і вважається успішним), і ваш стан все ще спрацьовує. Правильним шляхом було б:

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

2

PHP - мова, що не вводиться. Використання оператора подвійної рівності дозволяє вільно перевірити змінну.

Помірна перевірка значення дозволила б деяким подібним, але не рівним, значенням прирівнюватись як однакові:

  • ''
  • нуль
  • помилковий
  • 0

Усі ці значення дорівнювали б рівним за допомогою оператора подвійного рівного.


1

Змінні мають тип і значення.

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

Коли ви використовуєте ці змінні (в PHP), іноді ви не маєте гарного типу. Наприклад, якщо ви робите

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

PHP повинні перетворити ("на лиття") $ var в ціле число. У цьому випадку "$ var == 1" є істинним, оскільки будь-який не порожній рядок приводиться до 1.

Використовуючи ===, ви перевіряєте, що значення І ТИП рівні, тому "$ var === 1" неправдиво.

Це корисно, наприклад, коли у вас є функція, яка може повертати помилкові (помилка) та 0 (результат):

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

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

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

тому що тест полягає в тому, що повернене значення "є булевим і хибним", а не "може бути закинуто хибним".


що стосується не порожніх рядків, це насправді не так. "a" == 0 - ІСТИНА.
nickf


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

Усі відповіді поки що ігнорують небезпечну проблему з ===. Мимоволі було відмічено, але не підкреслено, що цілі та подвійні є різними типами, тому наступний код:

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