Невозможно получить доступ к переменной до её инициализации в IIFE JavaScript

Вопрос или проблема

Я получаю ошибку “Uncaught ReferenceError: Cannot access ‘Q12’ before initialization” внутри функции changeCssClassIfOldAndNewValuesAreDifferent. Есть идеи, почему? Спасибо.

const formController = (function () {
    return {
      'changeCssClassIfOldAndNewValuesAreDifferent': changeCssClassIfOldAndNewValuesAreDifferent
    };

    const formScope: any = $("form#userAnswerForm");
    const Q12: any = $('.persistable[id=Q12]', formScope);
    const Q23: any = $('.persistable[id=Q23]', formScope);

    function changeCssClassIfOldAndNewValuesAreDifferent() {
        $('input.persistable, select.persistable').not(Q12) //<---Ошибка ссылки
        .each(function () {
            console.log('каждый элемент ввода и выбора с классом persistable (изменение, mouseout)');
            const thisPersistable: any = $(this);
            const Q12_or_Q23_is_not_empty: boolean = !commonUtility.isEmpty(Q12) && 
            !commonUtility.isEmpty(Q23);
            ...
            ...
        });
    }
})();

$(function(){
    formController.changeCssClassIfOldAndNewValuesAreDifferent();
});

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

const formController = (function () {
    const formScope: any = $("form#userAnswerForm");
    const Q12: any = $('.persistable[id=Q12]', formScope);
    const Q23: any = $('.persistable[id=Q23]', formScope);

    return {
      'changeCssClassIfOldAndNewValuesAreDifferent': changeCssClassIfOldAndNewValuesAreDifferent
    };

    function changeCssClassIfOldAndNewValuesAreDifferent() {
        $('input.persistable, select.persistable').not(Q12) //<---Ошибка ссылки
        .each(function () {
            console.log('каждый элемент ввода и выбора с классом persistable (изменение, mouseout)');
            const thisPersistable: any = $(this);
            const Q12_or_Q23_is_not_empty: boolean = !commonUtility.isEmpty(Q12) && 
            !commonUtility.isEmpty(Q23);
            ...
            ...
        });
    }
})();

$(function(){
    formController.changeCssClassIfOldAndNewValuesAreDifferent();
});

Ответ или решение

Проблема, с которой вы столкнулись, заключается в том, что вы пытаетесь получить доступ к переменной Q12 до её инициализации. Это происходит из-за того, что вы определяете Q12 и Q23 после оператора return, в то время как функция changeCssClassIfOldAndNewValuesAreDifferent, возвращаемая из функционального выражения, использует Q12. В JavaScript, благодаря механизму поднятия (hoisting), переменные, объявленные с помощью const и let, не доступны до момента их объявления.

Чтобы исправить эту ошибку, вам нужно переместить объявления переменных Q12 и Q23 выше оператора return. Вот исправленный код:

const formController = (function () {
    const formScope = $("form#userAnswerForm");
    const Q12 = $('.persistable[id=Q12]', formScope);
    const Q23 = $('.persistable[id=Q23]', formScope);

    function changeCssClassIfOldAndNewValuesAreDifferent() {
        $('input.persistable, select.persistable').not(Q12) // Здесь ошибка больше не будет
        .each(function () {
            console.log('each persistable input and select listeners (change, mouseout)');
            const thisPersistable = $(this);
            const Q12_or_Q23_is_not_empty = !commonUtility.isEmpty(Q12) && 
            !commonUtility.isEmpty(Q23);
            // Дополнительная логика...
            ...
        });
    }

    return {
        'changeCssClassIfOldAndNewValuesAreDifferent': changeCssClassIfOldAndNewValuesAreDifferent
    };
})();

$(function(){
    formController.changeCssClassIfOldAndNewValuesAreDifferent();
});

Теперь Q12 и Q23 инициализируются до того, как функция changeCssClassIfOldAndNewValuesAreDifferent попытается их использовать. Это полностью устраняет проблему с ошибкой "Не удаётся обратиться к ‘Q12’ до инициализации".

Таким образом, разместив инициализацию переменных перед использованием, вы избежите возникновения ошибок, связанных с областью видимости переменных.

Оцените материал
Добавить комментарий

Капча загружается...