Большинство программистов на 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.
Рекомендации
- Равенство в JavaScript: === против ==
- ECMAScript.next: обновление «TXJS» от Eich
- NaN и Бесконечность в JavaScript
- es6-shim — функциональность ECMAScript 6 в ECMAScript 5