Чем отличается двойное равно от тройного js
Перейти к содержимому

Чем отличается двойное равно от тройного js

  • автор:

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

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

В программировании часто нужно сравнивать переменные между собой. Если мы хотим знать равны ли переменные друг другу или какая из двух переменных больше, то сделать это можно с помощью операторов сравнения. Создадим две переменные x и y.

const x = 100;
const y = 100;

Оператор равно (===) / (==)

Для сравнения на строгое равенство используется тройное равно (===), а на нестрогое равенство — двойное равно (==). Как узнать, что эти две переменные равны? Запускаем следующий код в консоли и получаем ответ в качестве булевого значения (true / false). Если вернулось true, значит значение переменной x равно значению переменной y.

console.log(x === y ); // true

В этом случае для сравнения мы использовали оператор строгого равенства, поскольку у обоих переменных одинаковый тип данных — number. Но что произойдет, если у сравниваемых переменных будет разный тип данных. Число, заключенное в кавычки — это строка. Несмотря на то, что у них одинаковые значения, мы получим false. Разные типы данных нельзя сравнивать между собой.

const x = 100; // number (число)
const y = ‘100’; // string (строка)

console.log(x === y ); // false

Оператор двойного равенства (==) сравнивает только по значению, не обращая внимания на типы данных.

const x = 100; // number
const y = ‘100’; // string

console.log(x == y ); // true

const x = 100; // number
const y = 100; // number

console.log(x == y ); // true

Оператор двойного равенства (==) разрешает сравнивать между собой значения разных типов данных. В этом и есть главное отличие тройного оператора (===) от двойного (==). В программировании не рекомендуется использовать нестрогое сравнение из-за риска возникновения ошибок на пустом месте. Всегда используйте только тройное равно (===!

Оператор не равно (!==)

Оператор строгого не равно (!==) сравнивает переменные по типу и значению, оператор нестрогого не равно (!=) сравнивает только по значению, игнорируя типы (работает по аналогии с (==) и крайне нежелателен к использованию). В примере ниже, мы ожидаемо получаем false, поскольку утверждение, что x не равно y, неверно.

const x = 50; // number (число)
const y = 50; // number (число)

console.log(x !== y ); // false

При сравнении разных типов данных, данное утверждение становится верным.

const x = 50; // number (число)
const y = ’50’; // string (строка)

console.log(x !== y ); // true

Оператор больше чем (>)

Утверждение, что x больше, чем y верно и возвращает нам true.

const x = 60;
const y = 50;

console.log(x > y); // true

Оператор больше или равно (>=)

А утверждение, что x больше или равен y, неверно.

const x = 40;
const y = 50;

console.log(x >= y); // false

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

Сравнение массивов

Логика сравнения ссылочных типов данных (массивов и объектов) существенно отличается.

В область памяти переменной с массивом или объектом записывается не значение, а ссылка (адрес) на эту переменную. Поэтому когда мы сравниваем два абсолютно одинаковых массива, то получаем false. Они уже по своей сути не могут быть равны, ведь ссылки на них разные. Ссылочный тип данных содержит указатель на объект, а не сам объект.

Оператор равно ===

const x = [1,2,3];
const y = [1,2,3];

console.log(x === y ); // false

Необычность ситуации с ссылочным типом данных состоит в том, что при иных обстоятельствах, одинаковые массивы могут быть равны. Что имеется в виду? Мы создали переменную x и присвоили ей массив, затем в переменную y передали значение переменной x. Теперь обе переменные содержат одинаковые значения, что подтверждает возвращаемое true. Чем же эта ситуация отличается от предыдущей? Все дело в том, что в переменную x мы записали адрес на массив и передали его в переменную y. Таким образом обе переменные имеют одинаковый адрес и ссылаются на один и тот же объект, а значит они равны между собой. В первом же случае массивы были одинаковые, но адреса (ссылки) — разные. При сравнивании объектов, механизм будет точно такой же.

const x = [3,4,5];
const y = x;
console.log(y); // [3,4,5]

console.log(x === y ); // true

Создано 22.01.2021 10:10:56

  • Михаил Русаков
  • Копирование материалов разрешается только с указанием автора (Михаил Русаков) и индексируемой прямой ссылкой на сайт (http://myrusakov.ru)!

    Добавляйтесь ко мне в друзья ВКонтакте: http://vk.com/myrusakov.
    Если Вы хотите дать оценку мне и моей работе, то напишите её в моей группе: http://vk.com/rusakovmy.

    Если Вы не хотите пропустить новые материалы на сайте,
    то Вы можете подписаться на обновления: Подписаться на обновления

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

    Порекомендуйте эту статью друзьям:

    Если Вам понравился сайт, то разместите ссылку на него (у себя на сайте, на форуме, в контакте):

    1. Кнопка:
      Она выглядит вот так:
    2. Текстовая ссылка:
      Она выглядит вот так: Как создать свой сайт
    3. BB-код ссылки для форумов (например, можете поставить её в подписи):

    Комментарии ( 0 ):

    Для добавления комментариев надо войти в систему.
    Если Вы ещё не зарегистрированы на сайте, то сначала зарегистрируйтесь.

    Copyright © 2010-2024 Русаков Михаил Юрьевич. Все права защищены.

    Операторы сравнения в JavaScript: тройной знак равенства и двойной знак равенства

    Вы видели двойные и тройные знаки равенства в JavaScript. Но что они? Если коротко: == преобразует тип, а === не преобразует тип.

    Двойной знак равенства (==) проверяет только равенство значений. Он выполняет приведение типов. Это означает, что перед проверкой значений он преобразует типы переменных, чтобы привести их в соответствие друг к другу.

    Тройной знак равенства (===) не выполняет приведение типов. Он проверяет, имеют ли сравниваемые переменные одинаковое значение и тип.

    Рассмотрим несколько примеров:

    Пример 1

    const foo = "test" const bar = "test" console.log(foo == bar) //true console.log(foo === bar) //true

    Значение и тип у foo и bar одинаковые. Поэтому результат для обоих — true.

    Пример 2

    const number = 1234 const stringNumber = '1234' console.log(number == stringNumber) //true console.log(number === stringNumber) //false

    Значения number и stringNumber выглядят одинаковыми. Но number имеет тип Number, а stringNumber имеет тип string. Даже если значения переменных одинаковы, тип не совпадает. Поэтому оператор == возвращает значение true. Но при проверке значения и типа значение равно false.

    Пример 3

    console.log(0 == false) //true console.log(0 === false) //false

    Значение 0 при проверке с false является тем же. 0 и false имеют одинаковое значение для JavaScript. Но при проверке с помощью тройного оператора значение ложно, потому что 0 имеет тип number, а false – boolean.

    Пример 4

    const str = "" console.log(str == false) //true console.log(str === false) //false

    Значение пустой строки и false – это в JavaScript то же самое. Следовательно, == возвращает значение true. Но тип переменных отличается, поэтому === возвращает значение false.

    Когда использовать ==, а когда ===?

    Если есть сомнения, используйте ===. Это избавит вас от большого количества потенциальных ошибок.

    Если не нужен контроль входящих данных, используйте ==. Например, если API принимает от клиента «true» и true, используйте ==.

    Эта таблица показывает, насколько сложно сравнение в JavaScript.

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

    JavaScript предоставляет три оператора сравнения величин:

    • равенство («двойное равно») использует == (en-US),
    • строгое равенство («тройное равно» или «идентично») использует === (en-US),
    • и Object.is (новшество из ECMAScript 6).

    Выбор оператора зависит от типа сравнения, которое необходимо произвести.

    В общих чертах, двойное равно перед сравнением величин производит приведение типов; тройное равно сравнивает величины без приведения (если величины разных типов, вернёт false , даже не сравнивая); ну и Object.is ведёт себя так же, как и тройное равно, но со специальной обработкой для NaN , -0 и +0 , возвращая false при сравнении -0 и +0 , и true для операции Object.is(NaN, NaN) . (В то время как двойное или тройное равенство вернут false согласно стандарту IEEE 754.) Следует отметить, что все эти различия в сравнениях применимы лишь для примитивов. Для любых не примитивных объектов x и y , которые имеют одинаковые структуры, но представляют собой два отдельных объекта (переменные x и y не ссылаются на один и тот же объект), все операторы сравнения вернут false .

    Сравнение с использованием ==

    Перед сравнением оператор равенства приводит обе величины к общему типу. После приведений (одного или обоих операндов), конечное сравнение выполняется также как и для === . Операция сравнения симметрична: A == B возвращает то же значение, что и B == A для любых значений A и B .

    В следующей таблице приведены результаты сравнения оператора равенства для различных значений:

    В таблице выше, ToNumber(A) пытается перед сравнением привести свой аргумент к числу. Такое поведение эквивалентно +A (унарный оператор + ). Если ToPrimitive(A) получает объект в качестве аргумента, то производятся попытки привести его к примитиву, вызывая на нем методы A.toString и A.valueOf .

    Традиционно (и в соответствии с ECMAScript), ни один из объектов не равен undefined или null . Но большинство браузеров позволяет определённому классу объектов (в частности, объектам document.all для любой страницы) эмулировать значение undefined. Оператор равенства вернёт значение true для null == A и undefined == A , тогда, и только тогда, когда объект эмулирует значение undefined . Во всех остальных случаях объект не может быть равен undefined или null .

    var num = 0; var obj = new String("0"); var str = "0"; var b = false; console.log(num == num); // true console.log(obj == obj); // true console.log(str == str); // true console.log(num == obj); // true console.log(num == str); // true console.log(obj == str); // true console.log(null == undefined); // true // оба false, кроме очень редких случаев console.log(obj == null); console.log(obj == undefined); 

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

    Строгое равенство с использованием ===

    Строгое равно проверяет на равенство две величины, при этом тип каждой из величин перед сравнением не изменяется (не приводится). Если значения имеют различающиеся типы, то они не могут быть равными. С другой стороны все не числовые переменные, принадлежащие одному типу, считаются равными между собой, если содержат одинаковые величины. Ну и, наконец, числовые переменные считаются равными, если они имеют одинаковые значения, либо одна из них +0 , а вторая -0 . В то же время, если хотя бы одна из числовых переменных содержит значение NaN , выражение вернёт false .

    var num = 0; var obj = new String("0"); var str = "0"; var b = false; console.log(num === num); // true console.log(obj === obj); // true console.log(str === str); // true console.log(num === obj); // false console.log(num === str); // false console.log(obj === str); // false console.log(null === undefined); // false console.log(obj === null); // false console.log(obj === undefined); // false 

    Практически всегда для сравнения следует использовать оператор строгого равенства. Для всех значений, за исключением числовых используется очевидная семантика: величина равна только сама себе. Как было сказано выше для числовых типов можно выделить два особых случая. Во-первых, сравнение +0 и -0 . Знак для нуля введён для упрощения некоторых вычислений с плавающей запятой, однако, с точки зрения математики, разницы между +0 и -0 не существует, поэтому оператор строгого равенства считает их равными. Во-вторых, сравнение величин NaN . NaN (Not a number) представляет из себя значение не определённой величины, которое применяется для не чётко определённых математических задач (например +∞ + -∞ ). Для оператора строго равенства NaN не равен ни одной из величин, в том числе и самому себе (единственный случай, когда (x!==x) вернёт true).

    Равенство одинаковых величин

    Равенство одинаковых величин определяет функциональную идентичность во всех контекстах сравниваемых величин. (Данный способ сравнения основывается на принципе подстановки Барбары Лисков.) Рассмотрим пример попытки изменения неизменяемого (immutable) свойства :

    // Добавление неизменяемого свойства NEGATIVE_ZERO (отрицательный ноль) в конструктор Number. Object.defineProperty(Number, "NEGATIVE_ZERO",  value: -0, writable: false, configurable: false, enumerable: false, >); function attemptMutation(v)  Object.defineProperty(Number, "NEGATIVE_ZERO",  value: v >); > 

    При попытке изменения неизменяемого свойства, вызов Object.defineProperty выбросит исключение, однако, если новое свойство равняется старому, изменений не произойдёт и исключение не будет выброшено. Если v содержит -0 , изменений не произойдёт, а значит, код отработает без выброса исключений. Однако, если же v содержит +0 , Number.NEGATIVE_ZERO утратит свою неизменяемую величину.

    Именно для сравнения нового и текущего неизменяемых свойств используется сравнение одинаковых величин, представленное методом Object.is .

    Равенство одинаковых величин и нулей

    Аналогично равенству одинаковых величин, но +0 и -0 считаются равными.

    Равенство одинаковых величин и нулей не предоставляется как JavaScript API, но может быть реализовано с помощью пользовательского кода:

    function sameValueZero(x, y)  if (typeof x === "number" && typeof y === "number")  // x и y равны (могут быть -0 и 0) или они оба равны NaN return x === y || (x !== x && y !== y); > return x === y; > 

    Равенство одинаковых величин и нулей отличается от строгого равенства тем, что принимает каждое значение NaN равным любому другому значению NaN , а от равенства одинаковых величин тем, что принимает -0 равным 0 . Подобное поведение обычно оказывается самым уместным при поиске в списках, особенно при работе с NaN . Данная стратегия сравнения используется в методах Array.prototype.includes() , TypedArray.prototype.includes() (en-US) , а так же в Map (en-US) и Set для оценки равенства ключей.

    Спецификации для равенства, строгого равенства и равенства одинаковых величин

    В стандарте ES5, сравнение выполняемое оператором == (en-US) описывается в секции 11.9.3, The Abstract Equality Algorithm. Описание оператора === (en-US) находится в секции 11.9.6, The Strict Equality Algorithm. В секции 9.12, The SameValue Algorithm ES5 описывает операцию сравнение одинаковых величин для внутреннего движка JS. Строгое равенство и равенство одинаковых величин, практически одинаковы, за исключением обработки числовых типов. ES6 предлагает использовать алгоритм сравнения одинаковых величин через вызов Object.is .

    Как понимать все эти способы сравнения?

    До выхода редакции ES6 считалось, что оператор строгого равенства просто «улучшенная» версия оператора нестрогого равенства. Например, некоторые считали, что == просто улучшенная версия === потому, что первый оператор делает всё то же, что и второй, плюс приведение типов своих операндов. То есть 6 == «6». (Или же наоборот: оператор нестрогого равенства базовый, а оператор строгого равенства просто его улучшенная версия, ведь он добавляет ещё одно условие — требует, чтобы оба операнда были одного и того же типа. Какой вариант ближе вам, зависит только от вашей точки зрения на вещи.)

    Но эти точки зрения уже нельзя применить к новому методу сравнения Object.is из новой редакции ES6. Нельзя сказать, что Object.is более или менее строг относительно существующих способов сравнения, или что это нечто среднее между ними. Ниже в таблице показаны основные различия операторов сравнения. Object.is интересен тем, что различает -0 и +0, а также умеет сравнивать два не числа NaN.

    x y == === Object.is SameValueZero
    undefined undefined ✅ true ✅ true ✅ true ✅ true
    null null ✅ true ✅ true ✅ true ✅ true
    true true ✅ true ✅ true ✅ true ✅ true
    false false ✅ true ✅ true ✅ true ✅ true
    ‘foo’ ‘foo’ ✅ true ✅ true ✅ true ✅ true
    0 0 ✅ true ✅ true ✅ true ✅ true
    +0 -0 ✅ true ✅ true ❌ false ✅ true
    +0 0 ✅ true ✅ true ✅ true ✅ true
    -0 0 ✅ true ✅ true ❌ false ✅ true
    0n -0n ✅ true ✅ true ✅ true ✅ true
    0 false ✅ true ❌ false ❌ false ❌ false
    «» false ✅ true ❌ false ❌ false ❌ false
    «» 0 ✅ true ❌ false ❌ false ❌ false
    ‘0’ 0 ✅ true ❌ false ❌ false ❌ false
    ’17’ 17 ✅ true ❌ false ❌ false ❌ false
    [1, 2] ‘1,2’ ✅ true ❌ false ❌ false ❌ false
    new String(‘foo’) ‘foo’ ✅ true ❌ false ❌ false ❌ false
    null undefined ✅ true ❌ false ❌ false ❌ false
    null false ❌ false ❌ false ❌ false ❌ false
    undefined false ❌ false ❌ false ❌ false ❌ false
    ❌ false ❌ false ❌ false ❌ false
    new String(‘foo’) new String(‘foo’) ❌ false ❌ false ❌ false ❌ false
    0 null ❌ false ❌ false ❌ false ❌ false
    0 NaN ❌ false ❌ false ❌ false ❌ false
    ‘foo’ NaN ❌ false ❌ false ❌ false ❌ false
    NaN NaN ❌ false ❌ false ✅ true ✅ true

    Когда использовать Object.is(), а когда ===

    Особое поведение Object.is по отношению к нулям, вероятно, будет представлять интерес при реализации определенных схем метапрограммирования, особенно в отношении дескрипторов свойств, когда желательно, чтобы ваш алгоритм имел такое же поведение, как Object.defineProperty . В случае, если вам этого не требуется, рекомендуется избегать Object.is и вместо этого использовать === . Как правило, даже при необходимости сравнения NaN -значений, эффективнее выполнить проверку таких значений отдельно, при помощи метода isNaN , чем выяснять, как окружающие вычисления могут повлиять на знаки нулей и как это отразится на вашем алгоритме.

    Вот неполный список встроенных методов и операторов, при использовании которых, различие между -0 и +0 может оказаться важным для вашего кода:

    Рассмотрим следующий пример:

    const stoppingForce = obj.mass * -obj.velocity; 

    Если obj.velocity равно 0 (или вычисляется как 0 ), в этом месте возникает -0 и присваивается в stoppingForce .

    In some cases, it’s possible for a -0 to be introduced into an expression as a return value of these methods even when no -0 exists as one of the parameters. For example, using Math.pow to raise -Infinity to the power of any negative, odd exponent evaluates to -0 . Refer to the documentation for the individual methods.

    It’s possible to get a -0 return value out of these methods in some cases where a -0 exists as one of the parameters. E.g., Math.min(-0, +0) evaluates to -0 . Refer to the documentation for the individual methods.

    Each of these operators uses the ToInt32 algorithm internally. Since there is only one representation for 0 in the internal 32-bit integer type, -0 will not survive a round trip after an inverse operation. E.g., both Object.is(~~(-0), -0) and Object.is(-0 > 2, -0) evaluate to false .

    Relying on Object.is when the signedness of zeros is not taken into account can be hazardous. Of course, when the intent is to distinguish between -0 and +0 , it does exactly what’s desired.

    Caveat: Object.is() and NaN

    The Object.is specification treats all instances of NaN as the same object. However, since typed arrays are available, we can have distinct floating point representations of NaN which don’t behave identically in all contexts. For example:

    const f2b = (x) => new Uint8Array(new Float64Array([x]).buffer); const b2f = (x) => new Float64Array(x.buffer)[0]; // Get a byte representation of NaN const n = f2b(NaN); // Change the first bit, which is the sign bit and doesn't matter for NaN n[0] = 1; const nan2 = b2f(n); console.log(nan2); // NaN console.log(Object.is(nan2, NaN)); // true console.log(f2b(NaN)); // Uint8Array(8) [0, 0, 0, 0, 0, 0, 248, 127] console.log(f2b(nan2)); // Uint8Array(8) [1, 0, 0, 0, 0, 0, 248, 127] 

    Смотрите также

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

    Операторы сравнения приводят выражение к логическому типу: true или false . Часто операторы сравнения используются в условных конструкция: if…else, тернарный оператор и др.

    Равно (==) и тройное равно (===)

    Разница в том, что обычное равно сравнивает только значение, а тройное равно (строгое) сравнивает еще и тип данных.

    При использовании операторов сравнения с разными типами данных, JS приводит их к числу и затем выполняет сравнение.

    Рассмотрим следующий пример:

    5 == '5' // true - оба значения будут преобразованы в число 5 === '5' // false - значение справа не будет преобразовано в число, т.к. мы хотим сделать сравнение значения и типа данных true == 1 // true true === 1 // false

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

    Не равно (!=) и строгое не равно (!==)

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

    Допустим, у нас есть есть пользователь и у него есть поле role, где может быть несколько разных ролей (читатель, редактор, админ, суперадмин), а мы хотим чтобы на сайте для админов не отображалась реклама (текст, какой-то блок и т.д.):

    const user = < name: 'John', role: 'admin', . >if (user.role !== 'admin') < //. показывать рекламу >

    Вот так просто мы можем проверить является ли пользователь админом.

    Также как и предыдущие операторы, оператор != сравнивает только значение, а оператор !== — значение и тип данных

    5 != '5' // false - оба значения будут приведены к строке и затем будут сравниваться 5 !== '5' // true - у одного операнда тип число, у второго строка. Они не равны true != 1 // false

    Больше (>) и меньше (<)

    Данные операторы работают как и в математике:

    5 > 5 // false 6 > 5 // true 4 > 5 // false 5 < 5 // false 6 < 5 // false 4 < 5 // true

    Больше или равно (>=), меньше или равно (<=)

    Эти операторы также очень просты в использовании, они нужны на случай если мы хотим сделать проверку операндов — больше/менньше они или может быть равны:

    5 >= 5 // true 6 >= 5 // true 4 >= 5 // false 5 

    Добавить комментарий

    Ваш адрес email не будет опубликован. Обязательные поля помечены *