Почему null и undefined типа DOMWindow?

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

Object.prototype.toString.call(undefined); // "[object Undefined]"
Object.prototype.toString.call(null); // "[object Null]"

Однако, когда вы запускаете этот код в PhantomJS, в обоих случаях вывод [object DOMWindow].

Это кажется странным, поскольку undefined и null являются общими типами. Оператор typeof работает так же, как и в других средах (включая typeof null === "object" quirk), поэтому, по-видимому, PhantomJS, по крайней мере, имеет концепцию типа undefined:

typeof undefined; // "undefined"

Он также утверждает, что Object.prototype.toString содержит собственный код, который может указывать на то, что Phantom сам ничего не делает для изменения реализации (я не знаю, если это случай или нет, хотя - я не был может найти что-нибудь полезное в источнике):

Object.prototype.toString.toString(); // "function toString() { [native code] }"

Итак, почему PhantomJS не использует (или хотя бы выставляет) правильные значения свойств [[Class]] для null и undefined, и есть ли способ изменить это? Я знаю, что я мог бы использовать другой метод для определения типа, но мне бы этого не хотелось.

Ответ 1

Это комбинация двух вещей. A script выполняется на веб-странице, поэтому глобальный объект является объектом window, о чем свидетельствует:

console.log(this.toString()); // [object DOMWindow]

Кроме того, существует проблема с той версией реализации JavaScript, которая фальсифицирует цепочку прототипов объекта в вышеуказанном условии.

Скорее всего, это будет исправлено в какой-то будущей версии.

Ответ 2

Я признаю, что я добираюсь сюда, но статья в MDN на Object.toString() упоминает:

Начиная с JavaScript 1.8.5 toString(), вызванного null возвращает [object Null], а undefined возвращает [object Undefined], как определено в пятом выпуске ECMAScript и последующих исправлениях. См. Использование toString для определения типа объекта.

Затем связанный раздел описывает конструкцию Object.prototype.toString(null), которую вы используете. Таким образом, кажется, что мы можем разумно подчёркивать null, а undefined - это новое (-ish) дополнение/исправление к Javascript, которое движок PhantomJS (Apple JavaScriptCore, у которого неизвестно, какая версия) еще не реализована. Тем не менее, это правильно работает в Safari 6, поэтому, возможно, стоит сообщить об этом как об ошибке, требуя соблюдения ES5.

Ответ 3

Если это всего лишь 2 типа, я думаю, вы можете просто окружить свою проблему этим.

Object.prototype.toString = function(obj){

    if(typeof(obj) == "undefined"){
        return "[object Undefined]";
    }

    if(typeof(obj) == "null"){
        return "[object Null]";
    }

    return obj.toString();

}