Подтвердить что ты не робот

Почему значение typeof null изменяется внутри цикла?

Выполнение этого фрагмента в консоли Chrome:

function foo() {
    return typeof null === 'undefined';
}
for(var i = 0; i < 1000; i++) console.log(foo());
4b9b3361

Ответ 2

На самом деле это ошибка V8 JavaScript (Wiki).

Этот движок используется в Chromium, Maxthron, Android OS, Node.js и т.д.

Относительно простой описание ошибки вы можете найти в этом разделе Reddit:

Современные механизмы JavaScript скомпилируют JS-код в оптимизированный машинный код когда он выполняется (Just In Time компиляция), чтобы заставить его работать быстрее. Однако шаг оптимизации имеет некоторые начальные эксплуатационные издержки в обмен на долгосрочное ускорение, поэтому двигатель динамично решает зависит ли метод от того, как обычно он используется.

В этом случае появляется ошибка только в оптимизированном пути, в то время как неоптимизированный путь работает нормально. Поэтому сначала метод работает как но если он вызвал в цикле достаточно часто в какой-то момент, движок решит оптимизировать его и заменит его на багги версия.

Эта ошибка, по-видимому, исправлена ​​в V8 (commit), а также в отчете об ошибке Chromium () и NodeJS (commit).

Ответ 3

Чтобы ответить на прямой вопрос о том, почему он изменился, ошибка находится в подпрограмме оптимизации JIT для двигателя V8 JS, используемого Chrome. Сначала код запускается точно так же, как написано, но чем больше вы его запускаете, тем больше возможностей для оптимизации оптимизации перевешивает затраты на анализ.

В этом случае, после повторного выполнения в цикле, компилятор JIT анализирует эту функцию и заменяет ее оптимизированной версией. К сожалению, анализ делает неправильное предположение, и оптимизированная версия на самом деле не дает правильного результата.

В частности, Reddit user RainHappens предлагает, что это ошибка в распространении типа:

Он также распространяет некоторые типы (как в каких типах переменная и т.д.). Там специальный "неопределяемый" тип, когда переменная undefined или null. В этом случае оптимизатор "null" не обнаруживается, поэтому его можно заменить на строку "undefined" для сравнения.

Это одна из трудных проблем с оптимизацией кода: как гарантировать, что код, который был перестроен для производительности, будет по-прежнему иметь тот же эффект, что и оригинал.