Ощущение неопределенности "Без тени"

У меня есть функция, которая проверяет текущий этап в последовательном потоке, основываясь на конкретной дисциплине, которая передается, и, согласно этому значению, назначает следующее значение в моем приложении Angular 2. Это выглядит примерно так:

private getNextStageStep(currentDisciplineSelected) {
    const nextStageStep = '';
        if (this.stageForDiscipline(this.currentDisciplineSelected) === 'step 1') {
            const nextStageStep = 'step 2';
        } else if (this.stageForDiscipline(this.currentDisciplineSelected) === 'step 2') {
            const nextStageStep = 'step 3';
        } else if (this.stageForDiscipline(this.currentDisciplineSelected) === 'step 3') {
            const nextStageStep = 'step 4';
        } else if (this.stageForDiscipline(this.currentDisciplineSelected) === 'step 4') {
            const nextStageStep = 'step 5';
        } else if (this.stageForDiscipline(this.currentDisciplineSelected) === 'step 5') {
            const nextStageStep = 'step 6';
    }
    return nextStageStep;
}

То, что я здесь делаю, возвращает значение "nextStageStep", потому что это то, что я буду потом, чтобы сделать правильный шаг шага.

Прямо сейчас, мой tslint подчеркивает каждое из событий "nextStageStep" с предупреждением "без теневых переменных". Если я удалю строку, где я инициализирую пустую строку, это предупреждение исчезнет, но затем я получаю сообщение об ошибке "Не могу найти nextStageStep", появляющееся в моей инструкции return.

В чем проблема с первоначальным предупреждением о затененной переменной, и есть ли альтернативный способ написать это, и/или я должен просто игнорировать предупреждение tslint в этой ситуации?

Ответ 1

ЛИНТЕР жалуется, потому что вы переопределяете одну и ту же переменную несколько раз. Таким образом, заменяя те, которые содержатся в закрытии, содержащем его.

Вместо повторного использования он просто использует его:

private getNextStageStep(currentDisciplineSelected) {
    let nextStageStep = '';
        if (this.stageForDiscipline(this.currentDisciplineSelected) === 'step 1') {
             nextStageStep = 'step 2';
        } else if (this.stageForDiscipline(this.currentDisciplineSelected) === 'step 2') {
             nextStageStep = 'step 3';
        } else if (this.stageForDiscipline(this.currentDisciplineSelected) === 'step 3') {
             nextStageStep = 'step 4';
        } else if (this.stageForDiscipline(this.currentDisciplineSelected) === 'step 4') {
             nextStageStep = 'step 5';
        } else if (this.stageForDiscipline(this.currentDisciplineSelected) === 'step 5') {
             nextStageStep = 'step 6';
    }
    return nextStageStep;
}

Ответ 2

Это связано с определением одной и той же переменной в разных областях. Вы определяете nextStageStep пределах области функций и внутри каждого блока if. Один из вариантов - избавиться от объявлений переменных в блоках if

if (this.stageForDiscipline(this.currentDisciplineSelected) === 'step 1') {
   nextStageStep = 'step 2';
} else if (this.stageForDiscipline(this.currentDisciplineSelected) === 'step 2') {
   nextStageStep = 'step 3';
} else if (this.stageForDiscipline(this.currentDisciplineSelected) === 'step 3') {
   nextStageStep = 'step 4';
} else if (this.stageForDiscipline(this.currentDisciplineSelected) === 'step 4') {
   nextStageStep = 'step 5';
} else if (this.stageForDiscipline(this.currentDisciplineSelected) === 'step 5') {
   nextStageStep = 'step 6';
}

Вот хороший ресурс по теневым переменным http://eslint.org/docs/rules/no-shadow

Ответ 3

Вы повторно объявляете ту же переменную const nextStageStep в каждом блоке if.

Juste заменить const nextStageStep = 'step 2'; с nextStageStep = 'step 2'; (и всех остальных случаях), и все будет в порядке.

Ответ 4

Добавить в: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const

ES6 const BLOCK-SCOPED, таким образом:


{
    const TAG='<yourIt>';
    console.log(TAG);
 }

 {
  const TAG = '<touchingBase NoImNOt="true">';
  console.log(TAG);
 }

 console.log(TAG);  // ERROR expected

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

Если мы не сможем повторно использовать имена переменных, мы закончим работу с нечитаемыми программами, которые неясны. а не сообщать.

Я считаю, что предупреждение ошибочно

Ответ 5

Обычно эта ошибка возникает, когда переменная в локальной области и переменная в содержащей области имеют одно и то же имя, происходит теневое копирование. Затенение делает невозможным доступ к переменной в содержащей области и скрывает, к какому значению относится идентификатор.

Обратитесь к этой статье за примерами кода, объясняющими это.

Ответ 6

Прежде всего, даже если вы продолжите с предупреждениями, ваша функция " getNextStageStep() " всегда будет возвращать пустое значение,

  • Потому что " const " является переменной области видимости, и

  • Он не поддерживает переопределение значения [Инициализированное значение не может быть изменено].

В return переменной блок " nextStageStep " содержит пустое значение строки, и внутренние блоки " nextStageStep " переменные не будут маскировать или переопределить внешний блок " nextStageStep " значение переменной.

Поэтому, когда вы возвращаете " nextStageStep ", он всегда будет возвращать пустую строку.

nextStageStep действия переменных " nextStageStep " внутренних блоков находится в том же диапазоне, если только блок, а здесь переменная " nextStageStep " внешнего блока полностью отличается от переменных " nextStageStep " внутреннего блока.

Поэтому, если вы хотите, чтобы ваш код работал, и если вы хотите использовать const переменные, используйте несколько операторов return внутри блоков if.

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

function  getNextStageStep(currentDisciplineSelected) {
    const nextStageStep = '';
    if (currentDisciplineSelected === 'step 1') {
        const nextStageStep = 'step 2';
        return nextStageStep;
    } else if (currentDisciplineSelected === 'step 2') {
        const nextStageStep = 'step 3';
        return nextStageStep;
    } else if (currentDisciplineSelected === 'step 3') {
        const nextStageStep = 'step 4';
        return nextStageStep;
    } else if (currentDisciplineSelected === 'step 4') {
        const nextStageStep = 'step 5';
        return nextStageStep;
    } else if (currentDisciplineSelected === 'step 5') {
        const nextStageStep = 'step 6';
        return nextStageStep;
    }
    return nextStageStep;
}
console.log(getNextStageStep('step 1'));

Но вместо написания этих многих операторов возврата лучше использовать переменную let которая позволяет переопределить значение переменной. Для вашей проблемы я думаю, что решение @toskv подходит.