Почему typeof null "объект"?
Я читаю главу 4 "Профессиональный Javascript для веб-разработчиков", в которой говорится, что пять типов примитивов: неопределенные, нулевые, логические, числа и строки.
Если null
примитив, почему typeof(null)
вернуть "object"
?
Разве это не значит, что null
передается по ссылке (я предполагаю, что здесь все объекты передаются по ссылке), следовательно, делая его НЕ примитивным?
12 ответов
В первой реализации JavaScript значения JavaScript были представлены как тег типа и значение, причем тег типа для объектов был 0
, а также null
был представлен как NULL
указатель (0x00
на большинстве платформ). В результате ноль 0
как тег типа, следовательно, фальшивая typeof
возвращаемое значение ( ссылка).
typeof null === 'object'; // This stands since the beginning of JavaScript
Для ECMAScript было предложено "исправить" (через подписку). Это привело бы к:
typeof null === 'null'
... но это изменение было отклонено из-за проблем с кодом, использующего эту специфическую "причуду" для проверки null
,
Если
null
примитив, почемуtypeof(null)
вернуть"object"
?
Потому что в спецификации так сказано.
11.4.3
typeof
операторПроизводство UnaryExpression:
typeof
UnaryExpression оценивается следующим образом:
- Пусть val будет результатом вычисления UnaryExpression.
- Если Тип (val) является Ссылкой, тогда
а. Если IsUnresolvableReference (val) имеет значение true, вернуть "undefined
".
б. Пусть val будет GetValue (val).- Вернуть строку, определенную типом (val) в соответствии с таблицей 20.
Как уже указывалось, в спецификации так сказано. Но так как реализация JavaScript предшествовала написанию спецификации ECMAScript, и спецификация была осторожна, чтобы не исправить ошибки начальной реализации, все еще остается законный вопрос о том, почему это было сделано именно таким образом. Дуглас Крокфорд называет это ошибкой. Киро Риск считает, что это что-то вроде:
Причина этого заключается в том, что
null
, по сравнению сundefined
, (был и остается) часто используется там, где появляются объекты. Другими словами,null
часто используется для обозначения пустой ссылки на объект. Когда Брендан Эйх создал JavaScript, он придерживался той же парадигмы, и имело смысл (возможно) возвращать "объект". На самом деле спецификация ECMAScript определяетnull
в качестве примитивного значения, которое представляет собой намеренное отсутствие какого-либо значения объекта (ECMA-262, 11.4.11).
нулевой
// Это стоит с самого начала JavaScript
typeof null === 'object';
Короткий ответ:
Это ошибка первого выпуска ECMAScript , которую, к сожалению, нельзя исправить, поскольку это нарушит существующий код.
Объяснение:
Однако на самом деле есть одно логическое объяснение тому, почему null является объектом в javascript.
В начальной версии JavaScript значения хранились в 32-битных блоках , которые состояли из небольшого тега типа (1–3 бита) и фактических данных значения . Теги типа хранились в младших битах единиц. Их было пятеро:
000: object. The data is a reference to an object.
1: int. The data is a 31 bit signed integer.
010: double. The data is a reference to a double floating point number.
100: string. The data is a reference to a string.
110: boolean. The data is a boolean.
Для всех объектов это было 000 как биты тега типа . null считался особым значением в JavaScript с самой первой его версии. null был представлением нулевого указателя . Однако в JavaScript, подобно C, не было указателей. Таким образом, null просто означал ничего или пустоту и представлялся всеми нулями . Следовательно, все его 32 бита были 0 . Поэтому всякий раз, когда интерпретатор JavaScrit читает null, он считает первые 3 бита типом «объект». Вот почему typeof null возвращает «объект».
Примечание:
Было предложено исправление для ECMAScript (через подписку), но оно было отклонено.Это привело бы к
typeof null === 'ноль'.
Из книги YDKJS
Это давняя ошибка в JS, но она, вероятно, никогда не будет исправлена. Слишком много кода в Интернете зависит от ошибки, и, следовательно, ее исправление вызовет гораздо больше ошибок!
Если
null
примитив, почемуtypeof(null)
вернуть "object
"?
вкратце: это ошибка в ECMAScript, и тип должен быть null
ссылка: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/null
В JavaScript null - это "ничего". Предполагается, что этого не существует. К сожалению, в JavaScript тип данных null является объектом. Вы можете считать ошибкой JavaScript, что typeof null является объектом. Он должен быть нулевым.
В JavaScript typeof null - это 'object', что неверно предполагает, что null является объектом. Это ошибка, которую, к сожалению, нельзя исправить, поскольку она нарушит существующий код.
Спецификация ECMAScript определяет эти типы данных языка :
6.1.1 Не определено Тип
6.1.2 Null Тип
6.1.3 Логический тип
6.1.4 Строка Тип
6.1.5 Символ Тип
6.1.6 Числовые типы
6.1.6.1 Номер Тип
6.1.6.2 BigInt Тип
6.1.7 Тип объекта
По историческим причинам Оператор несовместим с этой категоризацией в двух случаях:
-
typeof null == "object"
: это прискорбно, но с этим приходится жить. -
typeof
объекта функции оценивается как «функция», даже если согласно спецификации он имеет тип данных Object .
Другой оператор - instanceof
- может использоваться, чтобы узнать, наследуется ли объект от определенного прототипа. Например,
[1,2] instanceof Array
будет оценивать как истину.
Один из способов определить, является ли значение объектом, - использовать
Object
функция:
if (Object(value) === value) // then it is an object; i.e., a non-primitive
++Ответ автора:
Я думаю, что уже слишком поздно исправлять typeof. Изменение, предложенное для typeof null, нарушит существующий код.
Слишком поздно. С тех пор, как Microsoft создала свой собственный движок JavaScript и скопировала все функции и ошибки первой версии движка, все последующие движки скопировали эту ошибку, и теперь уже слишком поздно ее исправлять.
JS_TypeOfValue(JSContext *cx, jsval v)
{
JSType type = JSTYPE_VOID;
JSObject *obj;
JSObjectOps *ops;
JSClass *clasp;
CHECK_REQUEST(cx);
if (JSVAL_IS_VOID(v)) {
type = JSTYPE_VOID;
} else if (JSVAL_IS_OBJECT(v)) {
obj = JSVAL_TO_OBJECT(v);
if (obj &&
(ops = obj->map->ops,
ops == &js_ObjectOps
? (clasp = OBJ_GET_CLASS(cx, obj),
clasp->call || clasp == &js_FunctionClass)
: ops->call != 0)) {
type = JSTYPE_FUNCTION;
} else {
type = JSTYPE_OBJECT;
}
} else if (JSVAL_IS_NUMBER(v)) {
type = JSTYPE_NUMBER;
} else if (JSVAL_IS_STRING(v)) {
type = JSTYPE_STRING;
} else if (JSVAL_IS_BOOLEAN(v)) {
type = JSTYPE_BOOLEAN;
}
return type;
}
Для людей, которым интересен какой-то код, который сделал такое поведение, это ссылка для вас, ребята....
Это остаток ошибки из первой версии javascript.
«Это ошибка, которую, к сожалению, нельзя исправить, потому что это нарушит существующий код».
Ссылка и дополнительная информация: https://2ality.com/2013/10/typeof-null.html