理解“无阴影变量”的 tslint 警告
Posted
技术标签:
【中文标题】理解“无阴影变量”的 tslint 警告【英文标题】:Making Sense of 'No Shadowed Variable' tslint Warning 【发布时间】: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 警告吗?
【问题讨论】:
【参考方案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 情况)就可以了。
【讨论】:
以上是关于理解“无阴影变量”的 tslint 警告的主要内容,如果未能解决你的问题,请参考以下文章