Что означает ошибка ReferenceError: Cannot access uninitialized variable

Что означает ошибка ReferenceError: Cannot access uninitialized variable

Любопытная ошибка, которая находится совсем в другом месте

Ситуация: улучшаем код из статьи про автопереключение тёмной темы на сайте, чтобы одновременно работала ручная и автоматическая настройка. Идея такая: по нажатию автопереключателя добавлять в стили новый медиазапрос, чтобы браузер сам включал тёмную тему. 

Идём на StackOverflow, находим готовое решение и правим под себя все названия переменных и функций:

// получаем доступ к таблице стилей
const styleSheet = style.sheet;
function autoDarkLight() {
console.log('Вставляем новый медиазапрос в стили');
// формируем стиль
const mediaRuleText = `@media screen and (prefers-color-scheme: dark) {
		  body {
		    background: black;
		    color: white;
		      }
		}`;
	// добавляем его в CSS
	const mediaRuleIndex = styleSheet.insertRule(mediaRuleText);
}

Вставляем этот код в наш скрипт, обновляем страницу и нажимаем на переключатель, чтобы вызвать функцию autoDarkLight(). Но вместо добавления запроса компьютер выдаёт ошибку:

❌ ReferenceError: Cannot access uninitialized variable.

Что это значит: JavaScript попытался получить доступ к переменной, но в момент обращения выяснилось, что она не инициализирована: браузер под неё не выделил память и работать с ней нельзя.

Что делать с ошибкой ReferenceError: Cannot access uninitialized variable

Хитрость этой ошибки в том, что чаще всего проблема не там, где произошла ошибка, а в другом месте кода. Например, вот что выдаёт нам браузер в консоли:

Что означает ошибка ReferenceError: Cannot access uninitialized variable

Видно, что функция начала работать, выдала сообщение в консоль, а потом остановилась на 50-й строке кода. Идём в редактор кода смотреть, что у нас там написано:

Что означает ошибка ReferenceError: Cannot access uninitialized variable

Получается, что браузер ругается на строку const mediaRuleIndex = styleSheet.insertRule(mediaRuleText), но с ней вроде всё в порядке:

  • переменную mediaRuleIndex мы определяем прямо сейчас, поэтому проблема явно не в ней;
  • переменную styleSheet мы объявили в самом начале, когда вставили чужой фрагмент кода;
  • а mediaRuleText мы заполнили пятью строками выше, и с ней тоже всё хорошо.

На самом деле ошибка только проявилась в этой строке, но произошла она гораздо раньше, когда мы добавили в скрипт строку

const styleSheet = style.sheet;

Проблема с ней в том, что style — это не встроенный стандартный элемент для обращения к CSS-стилям, а просто обычная новая переменная. Мы её никак не объявляли заранее и ничего ей не присваивали, а сразу начали использовать. Компьютер не выделил для неё память, а значит, что всё, что основано на этой переменной, например styleSheet, тоже не инициализировано.

Именно по этой причине браузер ругается на строку 50, потому что ему говорят что-то сделать на основе неинициализированной переменной, а так нельзя. 

Как исправить: правильно определить переменную style:

const style = document.getElementsByTagName("style")[0];

Теперь браузер создаст новую переменную, выделит под неё память, наполнит нужными значениями и позволит что-то делать на её основе.

Задание со звёздочкой: попробуйте сами найти причину такой же ошибки в этом коде:

// main.js
import {createApp} from 'vue';
import App from 'components/App.vue';
// ...
// здесь компьютер выдаст ошибку
const application = createApp(App);

Текст:

Михаил Полянин

Редактор:

Максим Ильяхов

Художник:

Алексей Сухов

Корректор:

Ирина Михеева

Вёрстка:

Кирилл Климентьев

Соцсети:

Виталий Вебер

Получите ИТ-профессию
В «Яндекс Практикуме» можно стать разработчиком, тестировщиком, аналитиком и менеджером цифровых продуктов. Первая часть обучения всегда бесплатная, чтобы попробовать и найти то, что вам по душе. Дальше — программы трудоустройства.
Начать карьеру в ИТ
Получите ИТ-профессию Получите ИТ-профессию Получите ИТ-профессию Получите ИТ-профессию
easy