如何使用严格模式而不在 JSlint 中出错

问题描述

查看有关 JSlint 的所有信息(例如 herehere),讨论是这样的

始终使用严格模式,因为它会捕获更多错误。您所要做的就是将“use strict”放在代码的顶部。而已!再简单不过了……除非 JSlint 抱怨并告诉您将其放在函数范围内,否则您必须将所有代码放在一个巨大的函数中。

我有数百个用 javascript 编写的函数,并且至少 <body> 在加载时调用回调函数,所以我试图围绕我应该如何将我的所有函数放在另一个函数中,但仍然确保 <body> 元素仍然可以穿透外部函数并使用内部作用域调用我的函数

谁能告诉我如何为这样的事情实现严格模式

function foo(){
    "use strict"; /* Approach 1: Putting inside every function */
                  /* Extremely tedious and ugly */
    $('#example').text('Hello '+ bar());
}

function bar(){
    "use strict"; /* Approach 1: Putting inside every function */
                  /* Extremely tedious and ugly */
    return 'Beautiful';
}

function fooBar (){
    "use strict"; /* Approach 2: Putting once at the top of an outer function */
    
    /* But Now how does <body> call this function? */
    function foo(){
        "use strict";
        $('#example').text('Hello '+ bar());
    }

    function bar(){
        "use strict";
        return 'Beautiful';
    }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<body onload="foo();">
<p id='example'>
</p>
</body>

解决方法

在现代 JavaScript 中,应尽可能避免使用内联处理程序,因为它们需要全局污染,需要使用某些参数转义丑陋的引号,并且具有荒谬的作用域链规则。因此,尝试删除内联处理程序并将您的 JavaScript 放入 IIFE,这可以变得严格:

(() => {
  "use strict";

  function foo() {
    $('#example').text('Hello ' + bar());
  }

  function bar() {
    return 'Beautiful';
  }
  window.addEventListener('DOMContentLoaded',foo);
})();
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<body>
  <p id='example'>
  </p>
</body>

如果您有任何其他类似于 <body onload="foo();"> 的内联处理程序,我强烈建议将它们重构出来。

,

尽管CertainPerformance 的答案是IMO 最好的答案,但我仍然想在我意思的上下文中回答我自己的问题,也许不是我的措辞。

一些编程语言似乎不太关心范围(我在看你的 Python),但大多数成熟的语言,以 C++ 是最强大的,提供了某种形式的范围

/* Begin Pseudocode */
include <a>;             /* Include some external library */
external var external_a; /* Indicate that it is defined externally */
var global_a;            /* Create global scope variable */

function xyz (p_1,p_2); /* Declare global scope function */

function xyz (p_1,p_2){ /* Define function */
    return p_1 * external_a + p_2 * global_a; /* Example calculation */
}

Javascript 并没有真正导出,因此您必须将所有这些都放在一个函数中,并在一个类中返回一个对象,然后 hack 以获得私有与公共的感觉,有点像这样

(() =>{
    var global_a; /* Global function scope */
    let xyz;      /* Declare function */

    xyz = function  (p_1,p_2){ /* Define function */
        return p_1 * p_2; /* Example calculation */
    };

    return { /* Finally,we have to manually return the function */
             /* designating it as public in the process */
        xyz: xyz
    };
}(external_a); /* passed externally,essentially making it a global */

不得不以这种奇怪的方式重构你的代码库通常是一种糟糕的编程语言的危险信号,你实际上是在修改语法以获得你想要的功能,在这个过程中把自己变成一个准编译器,但我这种方法还有另一个问题:它会导致糟糕的编程实践,比如定义了变量但从未使用过。如果你通过 JSHint 运行上面的 javascript 代码,它会抱怨 xyz is defined but never used。从技术上讲这是正确的,但这是所有 API 的全部本质:编写一次,稍后使用......也许。然后,这导致了整个兔子洞探险,试图抑制一些 JSHint 错误(如 xyz 被定义但从未使用),同时不抑制其他错误(如 a 被定义但从未使用)。可能有一种方法可以配置 JSHint 来识别这种特殊情况,但我的观点是,应该有一种干净的方法来实现这种结果,并且应该只为这种方法配置 JSHint。

现在 Javascript 技术上确实有一个导出功能,它可以像这样使用,但对我来说,强语言应该创建一个基于文件的模块,而不是基于在该文件的大量修改版本上,而且该模块应该导入而不是导出

var module_a = (() =>{
    var global_a; /* function scope */
    let xyz;      /* Declare function */

    xyz = function  (p_1,p_2){ /* Define function */
        return p_1 * p_2; /* Example calculation */
    };

    return {
        xyz: xyz
    };
}(external_a); /* passed externally */

export module_a;

我想我想说的是,我觉得我会从这个社区得到很大的反击,即 Javascript 希望成为一种具有高级功能的 OO 语言,但对其进行了黑客攻击一件事揭示了一个弱点,然后必须再次被黑客攻击。 Javascript 在线社区未能解决这些缺点导致脱离现实像这样的在线教程 (source)

[A] 模块 [a] 是以模块化方式编写的独立且可重用的 JavaScript 代码块。在 ES6 之前,JavaScript 没有定义任何用于处理模块的语言结构。因此,编写模块化 JavaScript 涉及使用一些编码约定。

现在这是最诚实的教程之一,但编码约定似乎有点淡化和中性,以符合我的口味。本质上,作者的意思是没有干净的方法可以做到这一点,因此不幸的是,您必须破解它。

所以,我对我最初的问题的冗长回答是这样的:你必须将整个代码库(都是全局范围和易于使用的 API)放在一个匿名函数中,然后粘贴 {{1 }} 在顶部以便 JSHint 工作,然后无论您需要公开可用的 API 端点,您都会返回一个巨大的对象,然后当 JSHint 抱怨变量被声明但未使用时,您在那里粘贴 "use strict"; 注释,然后如果该评论不起作用(很可能已弃用),请删除该评论,然后将其用 (/* jshint line: ignore */ ... /* jshint unused: false */) 包围未使用的变量部分,然后在最后页面导出您返回的对象并将其导入其他地方并使用它。