命名空间模式导致 JSLint '函数在定义之前被使用' 错误

Posted

技术标签:

【中文标题】命名空间模式导致 JSLint \'函数在定义之前被使用\' 错误【英文标题】:Namespacing pattern causes JSLint 'function was used before it's defined' error命名空间模式导致 JSLint '函数在定义之前被使用' 错误 【发布时间】:2012-05-18 16:57:48 【问题描述】:

我正在使用以下命名空间模式:

var MyNamespace = new function () 
    var foo = function () 
        bar();
    ;
    var bar = function () 
        alert("bar");
    ;
    this.init = function () 
        foo();
    ;
;

$(document).ready(function() 
    MyNamespace.init();
);

JSLint 抱怨 bar 在定义之前就被使用了。然而foo 直到bar 被声明后才会被调用。该代码适用于我尝试过的所有浏览器:http://jsfiddle.net/jDKvz/

模式是每个How do I declare a namespace in javascript?,第二个答案。

我需要在这里修复什么,还是应该忽略 JSLint?

【问题讨论】:

好吧,如果你颠倒两个函数的顺序,JSLint 会很高兴,但你是否“需要”这样做是主观的。我不同意 JSLint 的所有观点,但在这种情况下,我可能只是更改代码以使其关闭。 @nnnnnn 我的真实项目要复杂得多,例如可能包含相互调用的函数。 在这种情况下,我很乐意在这一点上忽略 JSLint。虽然我可能会尝试使用 function foo() ... 语法而不是 var foo = function()... 来查看它是否有任何不同,因为必须记住你必须真正关心的 lint 警告/错误是很烦人的...... @Andrew 你用的是什么版本的 JSLint? hosted version 抱怨 new function 是一个“奇怪的结构”,但没有说 bar 是未定义的。 【参考方案1】:

我怀疑这是因为提升,变量和函数声明被解释器提升到顶部,很可能是它的看法:

var MyNamespace = new function () 
    var foo;
    var bar;

    foo = function () 
        bar();
    ;

    bar = function () 
        alert("bar");
    ;

    this.init = function () 
        foo();
    ;
;

现在foo = function () bar();; 内部的bar() 尚未被解析,它只是一个变量bar,而不是此时要调用的函数。

话虽如此,如果您的代码运行良好,您可以继续使用它,打开 strict mode 也很有帮助。

【讨论】:

【参考方案2】:

bar 是一个函数表达式而不是一个函数声明,这意味着它只有在被赋值后才能工作。您可以改用函数声明,jslint 不会再抱怨了。

function bar() 
    ...

另外,new Function 是不必要的,function 就足够了。

编辑:

似乎在这种情况下摆脱new 使用自动调用函数(function()()) 或对象文字

【讨论】:

它调用以下函数作为构造函数。 (function() ... ())怎么样 这个也可以,也是我喜欢的,不过这里也可以用new。 (function() ... ()) 在这里不起作用,构造函数什么都不返回。 关于此答案中的第一句话,问题中的代码按原样工作,因为bar 在实际使用时分配的。这里的问题是有效的代码和 JSLint 完全满意的代码之间的区别。【参考方案3】:

编辑:认为 JS 关闭了值,而不是变量。

JSLint 正在抱怨,因为它没有看到变量提升正在进行。只需在使用它们的函数之前定义其他函数使用的函数。它有助于使您的代码更具可读性,并关闭 JSLint。

例如:

var MyNamespace = new function () 
    var bar = function () 
        alert("bar");
    ;

    var foo = function () 
        bar();
    ;

    this.init = function () 
        foo();
    ;
;

【讨论】:

“闭包规则”?再想一想。 “对未定义的值关闭...” - 对变量而不是的关闭。问题中显示的代码将起作用,因为bar 是由调用foo() 的时间定义的。反转函数应该会关闭 JSLint,但原来的方式其实并没有错。 好吧,将答案更改为关于可读性,而不是关于错误的关闭内容。我不会告诉别人使用函数语句。

以上是关于命名空间模式导致 JSLint '函数在定义之前被使用' 错误的主要内容,如果未能解决你的问题,请参考以下文章

JSLint:在定义之前使用

“Model”是“命名空间”,但此处被当做“类型”来使用,是啥原因导致的哦,这段代码我写

namespace 命名空间

9-29 函数进阶_命名空间和作用域

函数的命名空间和作用域

模块