【问题标题】:Jslint claims variable is already defined? (1)Jslint 声明变量已定义? (1)
【发布时间】:2013-07-24 20:30:00
【问题描述】:
function wrapper() {
    var $R = {};

    $R.expandFont = function (direction, max_time) {
        // wtf? $R jslint error
        var self = this,
            el_prim = self[0],
            $R = {};

        alert(direction + max_time + el_prim + $R);
    };
}

这个 sn-p 给出错误:

line 573 character 13
'$R' is already defined.

我认为很明显之前没有定义过。

$R 是在外部范围内定义的,但这不应该是相关的。我应该能够定义一个与 JavaScript 同名的局部变量(语言)是函数范围的。是的,我知道它不是块作用域,而是函数作用域。

这是基本的范围规则。什么给了?

这是一个 jslint 错误吗?

【问题讨论】:

  • 你在使用prototype.js吗?它定义了$R。如果省略此代码并在控制台中输入 $R 会发生什么?
  • 当我通过 JS Lint 运行该代码时,它没有给我这个结果。
  • 成功设置 $R.something = function(){...};必须定义 $R。
  • 可能是因为你正在锯掉你坐的那根树枝……
  • @WilliamTweed — 据推测,当您创建缩减的测试用例时,您已将其缩减到您描述的问题消失的程度。

标签: javascript jslint


【解决方案1】:

这是 JSLint 中的一个新特性。由a commit 于 2013 年 7 月 24 日添加。以下示例演示了错误原因:

(function () {
    var a = 1; // This declaration...
    return function () {
        var a = 2; // ... is shadowed by this one.
    };
}());

似乎只有当 JSLint 遇到声明的变量 在函数范围内(不在全局范围内)时才会发出警告,该变量后来被遮蔽(这可能解释了为什么您的问题的评论者无法复制它)。

目前看来没有办法关闭这个警告。

Crockford 已 the following to say 告知此新警告:

JSLint 现在会在定义的 var 与外部作用域中的某物具有相同名称时发出警告。这是令人困惑的,因为读者无法轻易分辨出他正在查看哪个变量。有时这是一个错误,因为新变量不小心隐藏了旧变量。在某些情况下,旧的就是预期的。

一旦有机会,我会在http://jslinterrors.com 上获得一个完整解释这一点的页面。

【讨论】:

  • @WilliamTweed - 同意,这可能会降低代码的可读性,但我不同意不将其设为 opt-in 功能的决定。目前,您甚至无法选择退出。在您的情况下,如果您知道后代范围不需要 $R,那么它没有任何问题。
  • 对于那些想要关闭警告的人,我发现使用选项 shadow = true 将关闭警告。
【解决方案2】:

我认为您自己理解,如果您在函数的外部或内部范围内重命名 $R,则 JSLint “错误”将得到修复。

我决定写我的答案只是因为我认为对 JSLint 的目标存在误解。它不仅仅是一个从 JavaScript 语言的角度帮助您查找错误的工具。您可以将该工具视为本书JavaScript: The Good Parts 的插件。 Douglas Crockford 试图说明阅读代码的人可能会误解该语言的哪些结构。一些来自潜在的误解他宣布为“警告”,另一些为“错误”。来自“警告”或“错误”的一些可以被 cmets 抑制,如 /*jslint ... */ 另一个不是(如在 for 循环头中声明 var)。选择哪些潜在的误解应该被解释为“警告”,哪些是“错误”是非常主观的,并且仅代表 Douglas Crockford 的个人意思。

我并不总是同意 Douglas Crockford 的建议,但警告(“错误”):'$R' is already defined 我个人认为也很重要,因为难以阅读此类代码。我建议您也从 $R 变量中重命名一个。我想再强调一次,此类更改的目标不是修复 JavaScript 错误,而是提高您的程序对其他人的可读性

顺便说一句,我建议您仅在顶层使用所有大写字母的变量($R 看起来如此,独立于第一个 $ 字母)。见the JSLint recommendation about the naming convention的最后一句。

【讨论】:

    【解决方案3】:
    line 573 character 13
    '$R' is already defined
    

    这是因为已经定义了 $R。两种选择:

    更改变量名

    或者把你的代码改成这样:

    var $R = {};
    
    $R.expandFont = function (direction, max_time) {
        // wtf? $R jslint error
        var self = this,
            el_prim = self[0];
    
        $R = {};
    

    另外,请参阅 DC 在 redefinition 上的这篇帖子。

    【讨论】:

      【解决方案4】:

      显然,

      $R 引起了混乱。给 jslint 语法分析器和 SO 的成员。当您从外部范围移动到内部范围时,请更改它。

      $R$PR 之类的东西,或其他。

      当您可以简单地更改变量名称时,没有必要引起这种混乱。

      克罗克福德不是傻瓜。如果您选择遵循这些指南,这些都是很好的指南。

      【讨论】:

        猜你喜欢
        • 2011-11-13
        • 1970-01-01
        • 2011-04-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-03-24
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多