10. Undef
function undef(x) {
return !{ undefined: { undefined: 1 } }[typeof x][x];
}
В этой задаче нужно подобрать такой аргумент, тип которого был бы равен undefined
, но сам он при этом не был бы равен undefined
. Ибо если он будет равен undefined
, то вернётся !1
, т. е. false
. Если же тип не будет равен undefined
, то ключ, полученный при вычислении typeof x
не будет найден в объекте, вернётся undefined
, а из него нельзя достать какое-то свойство.
Начать имеет смысл с того, как же работает typeof
. Скорее всего читатель знаком с тем, что значение typeof
вычисляется «по таблице». Мол, Джаваскрипт вычисляет тип значения, и результат этой проверки просто соотносит со значением в этой таблице:
Тип | Результат |
---|---|
Undefined | "undefined" |
Null | "object" |
Boolean | "boolean" |
Number | "number" |
String | "string" |
Symbol | "symbol" |
BigInt | "bigint" |
Function | "function" |
Всё остальное | "object" |
Отсюда, например, и странности с тем, что typeof null
— это "object"
.
Изначально, кстати, никакой таблицы не было, и такое поведение null
было просто ошибкой в коде первой версии Джаваскрипта. Аксель Раушмайер писал об этом.
Однако, для этой таблицы есть одно исключение. Если у объекта есть внутреннее свойство [[IsHTMLDDA]]
, то он ведёт себя как undefined
в некоторых выражениях. В частности, при вычислении typeof
. Объекты с таким свойством не определяются самой спецификацией, но могут быть определены производителями браузеров. Описание такого поведения в спеке — это скорее узаконивание некоторых браузерных решений задним числом. Но к счастью, ведёт себя таким образом только один объект в браузере — document.all
.
Такое поведение было добавлено производителями браузеров специально, чтобы обойти часто используемую в прошлом проверку на определение того, насколько браузер старый. Матиас Байненс рассказывал об этом подробнее в 2013-м.
Таким образом, единственное решение этой задачи выглядит так:
undef(document.all)