【问题标题】:Making Sense of 'No Shadowed Variable' tslint Warning理解“无阴影变量”的 tslint 警告
【发布时间】:2017-12-04 19:16:39
【问题描述】:

我有一个函数可以根据传入的特定学科检查顺序流中的当前阶段,并根据该值在我的 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 用警告 no shadowed variables 在每个出现的 nextStageStep 变量下划线。如果我删除了我初始化为空字符串的行,警告就会消失,但随后我会收到错误,Cannot find nextStageStep 会出现在我的返回语句中。

原始阴影变量警告有什么问题,是否有替代方法来编写,和/或在这种情况下我应该简单地忽略 tslint 警告吗?

【问题讨论】:

    标签: javascript angular typescript tslint


    【解决方案1】:

    一般来说,
    当局部范围内的变量和包含范围内的变量同名时,就会发生阴影。阴影使得无法访问包含范围内的变量,并掩盖了标识符实际引用的值。

    const a = 'no shadow';
    function print() {
        console.log(a);
    }
    print(); // logs 'no shadow'.
    
    const a = 'no shadow';
    function print() {
        const a = 'shadow'; // TSLint will complain here.
        console.log(a);
    }
    print(); // logs 'shadow'.
    

    请参阅此article 以获取解释此问题的代码示例。

    【讨论】:

      【解决方案2】:

      找到并打开您的 tslint.json 文件并将以下设置设置为 false

       "no-shadowed-variable": false,
      

      使用 Visual Studio 时,可能需要重新启动 Visual Studio。

      【讨论】:

      • 当提供的代码示例明显包含该规则要防止的不需要的错误时,建议禁用 linting 规则似乎很危险。
      【解决方案3】:

      首先,即使您继续警告,您的函数“getNextStageStep()”也将始终返回空值,

      • 因为“const”a 是块作用域变量,并且

      • 不支持重新定义值[初始化值不能更改]。

      return 块中的变量“nextStageStep”包含空字符串值,内部块“nextStageStep”变量不会屏蔽或覆盖外部块的“nextStageStep”变量值。

      所以每当你返回“nextStageStep”时,它总是会返回空字符串。

      内部块“nextStageStep”变量范围仅在 if 块内,而外部块“nextStageStep”变量与内部块“nextStageStep”变量完全不同。

      因此,如果您希望您的代码工作并且如果您必须想要使用const 变量,那么请在 if 块中使用多个 return 语句。

      以下是我检查并正常工作的代码。你可以根据你的要求使用它。

      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 解决方案是合适的。

      【讨论】:

        【解决方案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,这不是阴影的情况 - 每个常量都正确地放在大括号内。

        如果我们不能重复使用变量名,我们最终会得到不可读的、晦涩难懂的程序。而不是告知。

        我认为警告是错误的

        【讨论】:

        • 您的示例没有隐藏常量T,但最初的问题是nextStageStep。阴影并不意味着该常量被非法重新定义(const x = 1; const x = 2),只是如果您错误地引用了哪个 var/const/let 可能会出现错误。是否允许遮蔽是一个见仁见智的问题,但您可以说这条规则在这里弥补了 OP 的错误,因此您可以看到它是有目的的。
        【解决方案5】:

        linter 抱怨是因为您多次重新定义同一个变量。从而替换包含它的闭包中的那些。

        不要重新声明它,只需使用它:

        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;
        }
        

        【讨论】:

        • 好吧,因为它是一个常数。将其更改为 let 或 var
        【解决方案6】:

        这与在不同范围内定义相同的变量有关。您在函数范围内和每个 if 块内定义 nextStageStep。一种选择是去掉 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

        【讨论】:

        • 除非nextStageStep 被声明为let,而不是const,否则这将不起作用
        【解决方案7】:

        您在每个 if 块中重新声明了相同的变量 const nextStageStep

        只需将 const nextStageStep = 'step 2'; 替换为 nextStageStep = 'step 2';(以及所有其他 if 情况)就可以了。

        【讨论】:

          猜你喜欢
          • 2019-04-05
          • 2019-07-06
          • 2019-08-13
          • 1970-01-01
          • 1970-01-01
          • 2019-05-02
          • 1970-01-01
          • 1970-01-01
          • 2017-10-24
          相关资源
          最近更新 更多