Статьи

Более строгое равенство в JavaScript: решение ECMAScript.next


Большинство программистов на JavaScript знают, что «нормального» равенства (==) следует избегать в пользу строгого равенства (===)
[1] . Тем не менее, время от времени вам нужно что-то даже более строгое, чем ===: если вы хотите проверить наличие NaN или хотите различить -0 и +0. В этом посте рассказывается о деталях и решении ECMAScript.next
[2] — операторе «есть».

Проверка на NaN

NaN не является строго равным самому себе, нарушая основной закон рефлексивности: в математике любое значение x всегда равно себе:

    x = x 

Этот закон не распространяется на === и NaN:

    > NaN === NaN
    false

Как следствие, вы не можете найти NaN в массивах через indexOf, потому что этот метод опирается на ===, чтобы определить, какие элементы массива равны его первому аргументу: 

    > [ NaN ].indexOf(NaN)
    -1

Если вы не можете использовать === для проверки на NaN, какова альтернатива? Существует глобальная функция isNaN (), но она проблематична, потому что она преобразует свой аргумент в число и, таким образом, возвращает true для многих значений, которые явно не являются NaN [3]

    > isNaN("foo")
    true

Пояснение: «foo», преобразованный в число, является NaN. 

    > Number("foo")
    NaN

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

    function myIsNaN(value) {
        return value !== value;
    }

Более понятная альтернатива — использовать isNaN () после проверки, является ли значение числом. Это позволяет избежать проблемного преобразования не чисел [3]

    function myIsNaN2(value) {
        return typeof value === 'number' && isNaN(value);
    }

ECMAScript.next будет иметь Number.isNaN (), фиксированную версию глобального isNaN ().

Различают между -0 и +0

Этот вариант использования встречается редко, но иногда вы можете захотеть различить -0 и +0, которые являются различными значениями в JavaScript. === не позволяет вам сделать это:

    > -0 === +0
    true

Как вы можете сделать различие? Оказывается, есть одно число, которое вы можете разделить на 0 — число 1. Деление 1 на -0 приводит к -Infinity, а деление его на +0 приводит к бесконечности. И эти две бесконечности можно различить по ===: 

    > 1 / -0
    -Infinity

    > 1 / +0
    Infinity
    
    > Infinity === -Infinity
    false

Более строгое равенство в ECMAScript.next: оператор «is»

ECMAScript.next будет иметь оператор
«is», который выполняет «более строгое равенство»: он считает NaN равным самому себе и различает -0 и +0. Его отрицание называется «нет». Примеры:

    > NaN is NaN
    true
    
    > -0 isnt +0
    true

Оператор дополняется функцией Object.is (), которую можно перенести обратно в более старые версии ECMAScript. В этих версиях это можно реализовать следующим образом (слегка отредактированная версия предложения ECMAScript.next ): 

    Object.is = function(x, y) {
        if (x === y) {
            // x === 0 => compare via infinity trick
            return x !== 0 || (1/x === 1/y);
        }

        // x !== y => return true only if both x and y are NaN
        return x !== x && y !== y;
    };

Почему в предложении ECMAScript.next используется название «egal»?

Причина, по которой в
предложении ECMAScript.next используется имя «egal» для оператора «is», связана с оригинальным документом о равенстве: «
Равные права для функциональных объектов или, чем больше вещи меняются, тем больше они одинаковы » Генри Г. Бейкер, 1990. Цитируя объяснение этой статьи о том, что его оператор равенства называется «egal»:

Egal — устаревший норманнский термин для равных, а Egalité — французское слово для социального равенства.

Попробовать Object.is ()

Если вы хотите попробовать Object.is (), вы можете использовать es6-shim
[4], который переносит часть ECMAScript.next (который является текущим кодовым именем для ECMAScript 6) в ECMAScript 5.

Рекомендации

  1. Равенство в JavaScript: === против ==
  2. ECMAScript.next: обновление «TXJS» от Eich
  3. NaN и Бесконечность в JavaScript
  4. es6-shim — функциональность ECMAScript 6 в ECMAScript 5