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

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

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

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

@BenAubin: Серьезно, внесенные вами правки вообще ничего не улучшили.

klutt 15.02.2021 02:43

@BenAubin Я понимаю, что вы хотите помочь, и это хорошо, но эти правки не улучшили ситуацию. И теперь, когда у вас есть столько репутации, ваши правки не попадут в очередь на рассмотрение, так что будьте осторожны с вашими правками.

klutt 15.02.2021 02:58

@klutt Мои правки были преднамеренными. OP внес изменения в течение нескольких минут после исходного сообщения, в котором запрашивались как Javascript, так и PHP, поэтому многие ответы относятся к обоим языкам. Как я упоминал в примечаниях к редактированию, мои правки вернули исходный контекст.

Ben Aubin 04.03.2021 06:09
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
526
3
327 857
13
Перейти к ответу Данный вопрос помечен как решенный

Ответы 13

Ответ принят как подходящий

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

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

Comparison Operators

┌──────────┬───────────┬───────────────────────────────────────────────────────────┐
│ Example  │ Name      │ Result                                                    │
├──────────┼───────────┼───────────────────────────────────────────────────────────┤
│$a ==  $b │ Equal     │ TRUE if $a is equal to $b after type juggling.            │
│$a === $b │ Identical │ TRUE if $a is equal to $b, and they are of the same type. │
└──────────┴───────────┴───────────────────────────────────────────────────────────┘

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

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

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

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

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

Loose comparisons with ==

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

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

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

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

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

Strict comparisons with ===

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

Кому-нибудь еще покажется странным, что "000" == "0000"?

nickf 17.09.2008 17:08

Возможно, строки, которые выглядят как числа, преобразуются в числа перед сравнением, если это правда, тогда 000 == 0000 имеет смысл.

Kevin 27.10.2008 05:47

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

Pim Jager 17.08.2009 15:50

@Pim Ну, есть еще несколько подобных случаев, например null != "0". В конце концов, вы находятся сравниваете яблоки с апельсинами, так сказать, так что это нормально. «0» на самом деле не null. Просто все они очень хорошо преобразуются в BOOL, с чем вы обычно хотите их сравнивать.

deceze 17.08.2009 16:41

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

deceze 17.08.2009 16:56

@ Рэйтлин, осторожно с массивом. Triple Equals дает false для разных массивов в javascript, но true для PHP, если их значения равны равный.

Pacerier 02.08.2013 14:34

@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 07.08.2013 21:03

остерегайтесь того факта, что нет ни <==, ни >==, поэтому false <= 0 будет true. php версии 5.4.27

gondo 25.04.2014 15:42

А что насчет пустой строки ''? хотелось бы видеть это добавлено в эту удивительно полезную таблицу! :-)

olli 17.07.2014 23:32

Будьте внимательны. Не всегда, если a==b и a==c, значит, a==c. Например, "" == false, "0" == false, но "" != "0".

MC Emperor 29.07.2016 00:26

По-видимому, 0 == "#" также является true в PHP. Безумие ++.

Mantriur 04.01.2019 20:56

Также обратите внимание на 1.0 !== 1

Jake 14.11.2020 03:37

Из PHP 8 при сравнении с числовой строкой PHP 8 использует сравнение чисел. В противном случае он преобразует число в строку и использует сравнение строк. Итак, 0 == 'foobar' - это false.

zvi 07.12.2020 21:14

Это здорово. Нечего добавить, кроме юмора. «Все мы - пыль на ветру, чувак».

Bradley W. Myers 11.03.2021 03:45

Вы могли бы использовать === для проверки того, является ли функция или переменная ложной, а не просто приравнивать к 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)

что здесь не то, что вам нужно.

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

@DavidThomas: Это не совсем то же самое, см. stackoverflow.com/questions/12598407/…

xdazz 04.05.2013 16:45

Я получил этот ответ DV, потому что он пришел через 30 минут после того, как самостоятельный ответ OP подробно описал то же понимание относительно слабо типизированных сравнений. Этот ответ javascript на первоначально и в настоящее время вопрос с тегами php действительно должен быть удален, но для этого необходимо будет подсчитать количество голосов с помощью усилий сообщества. Другими словами, необходимо гораздо больше DV для того, чтобы иметь место соответствующее курирование и удалить этот ответ (удаленного пользователя).

mickmackusa 01.09.2020 07:05

У переменных есть тип и значение.

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

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

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

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

При использовании === вы проверяете, что значение AND THE TYPE равны, поэтому "$ var === 1" ложно.

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

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

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

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

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

что касается непустых строк, это на самом деле неправда. "a" == 0 - ИСТИНА.

nickf 17.09.2008 11:56

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

Примеры:

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)

Nitpick: === вернет истину, только если оба операнда одного типа и значения равны =)

gnud 26.02.2009 12:16

@gnud Это именно то, что он показал в примере. Если бы это было просто сравнение типов, это было бы просто «сравнением типов», не так ли.

Rob Stevenson-Leggett 26.02.2009 12:34

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

uuɐɯǝʃǝs 13.04.2009 17:21

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

Jeremy C 23.10.2012 03:55

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

clauziere 19.03.2014 00:04

остерегайтесь того факта, что нет ни <==, ни >==, поэтому false <= 0 будет true. php версии 5.4.27

gondo 25.04.2014 15:42

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

Vladimir Despotovic 15.03.2016 15:18

Примечательно 1.0 !== 1

Jake 14.11.2020 03:36

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

== сравнивает объекты, используя имя объекта и их значения. Если два объекта относятся к одному типу и имеют одинаковые значения элементов, $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

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

true также соответствует 1 и false также соответствует 0

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

$var=1;

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

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

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

<?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 ==:

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

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

https://github.com/sentientmachine/php_equality_charts

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

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

  1. NAN != NAN, но NAN == true.

  2. == преобразует левый и правый операнды в числа, если left является числом. Итак, 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. Если вы добавляете 1 к числу, и они уже удерживают свое максимальное значение, они не переходят в цикл, вместо этого они приводятся к infinity.

  9. Свежий класс равен == 1.

  10. False - наиболее опасное значение, потому что False == для большинства других переменных, в основном противореча его назначению.

Надеяться:

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

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

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

Chazy Chaz 17.01.2017 01:42

Да, транзитивное свойство тройного равенства делает его более безопасным и масштабируемым.

Eric Leschinski 17.01.2017 02:55

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

Tim 16.01.2020 12:55

В частности, 1.0 !== 1, который может быть немного подвох, например floor(4 / 3) === 1 ? 'works as might be expected' : 'what?'

Jake 14.11.2020 03:33

@EricLeschinski floor(4/3) === 1 не имеет значения true, потому что floor возвращает float (хотя возвращаемое значение обязательно целое число, а не по типу) - отсюда и причина указать на эту ошибку. У JavaScript нет этой проблемы, потому что существует только один числовой тип (хотя из-за этого есть другие проблемы, такие как округление целых чисел).

Jake 15.11.2020 02:59

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

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

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

Двойное значение PHP равно ==:

В большинстве языков программирования оператор сравнения (==) проверяет, с одной стороны, тип данных, а с другой стороны, содержимое переменной на равенство. Стандартный оператор сравнения (==) в 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 Triple Equals ===:

Этот оператор также проверяет тип данных переменной и возвращает (bool) истину, только если обе переменные имеют одинаковое содержимое и один и тот же тип данных. Таким образом, будет правильным следующее:

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

== (Equal)

=== (Identical equal)

Пример =>

<?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
?> 

если мы введем cast $ 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
    ?> 

Другие вопросы по теме