DeepSource的JavaScript分析器介绍及应用

522 阅读5分钟

在编写代码时,我们的代码在第一次运行时几乎没有成功执行的时候。然后,在代码的每一次执行失败后,我们都会潜入错误日志中去寻找错误所在。不幸的是,我们最终在解决错误上花费的时间比实际需要的时间要多。而这在JavaScript的案例中真的很常见。

作为开发人员,我们在单元和功能测试的帮助下确保代码质量。我们可以用静态分析来补充这些测试计划,通过静态分析,我们现在可以在执行之前检查代码,以评估其质量和对编码标准的遵守。静态分析可以帮助我们发现我们人类自己无法发现的代码问题,从而确保整个项目的代码质量,并保持开发人员的效率。

今天,我们非常高兴地推出了对JavaScript的连续静态分析,检测470多个问题,如bug风险、反模式、性能和风格问题。

DeepSource JavaScript Analysis Results

支持的框架和语言标准

  • 所有版本的ECMAScript (ES3, ES5, ES2015 - ES2020)
  • React JSX
  • TypeScript
  • 所有主要的模块系统(CommonJS、ES模块和AMD)。
  • 流行的JavaScript风格指南(Airbnb谷歌标准)。

ESLint规则和插件

DeepSource JavaScript 分析器完全支持所有 ESLint 核心 JavaScript 规则,并且 100% 兼容 ESLint。除此之外,它目前还支持以下ESLint插件。

我们正在努力增加对更多插件的支持,以进一步提高分析能力。

使用JavaScript分析器

要开始分析你的JavaScript代码,在DeepSource上创建一个账户,在你的.deepsource.toml 文件中启用javascript 分析器,并激活分析。

配置样本(.deepsource.toml)

version = 1

test_patterns = ["*/test/**"]

exclude_patterns = [
    "public/**,",
    "dist/**"
]

[[analyzers]]
name = "javascript"
enabled = true

  [analyzers.meta]
  ecma_version = "2016"
  module_system = "commonjs"
  environment = [
    "nodejs",
    "browser",
    "jest",
  ]

  plugins = ["react"]
  style_guide = "airbnb"
  dialect = "typescript"

下面是分析器检测到的一些问题。

错误-风险

  1. 调试器不应该在生产代码中使用

    debugger 语句是用来告诉执行的JavaScript环境停止执行,并在代码的当前点启动调试器。在生产代码中使用

    它在生产代码中可以阻止浏览器执行代码,并打开一个适当的调试器。

    例子:

    function isTruthy(x) {
      debugger
      return Boolean(x)
    }
    
  2. 防止重新分配函数声明

    重写/重赋一个函数往往表明了一个错误或问题。它可以在运行时引起代码的bug。

    例子:

    function foo() {}
    foo = bar
    
    function foo() {
      foo = bar
    }
    
  3. 在条件语句中使用常量条件

    一个常量表达式(例如,一个字面意思)作为测试条件,可能是一个打字错误或开发触发的特定行为。它可能会在运行时破坏代码。

    例子:

    if (false) {
      doSomethingUnfinished()
    }
    
    if (void x) {
      doSomethingUnfinished()
    }
    
    do {
      doSomethingForever()
    } while ((x = -1))
    

反模式

  1. 倾向于使用===!== 而不是==!=

    使用类型安全的平等运算符===!== ,而不是普通的对应运算符==!= ,被认为是很好的做法。例如,这些在理想情况下应该是假的语句 被认为是真的。

  2. 防止使用alert

    JavaScript的alert,confirm, 和prompt 函数被广泛认为是碍眼的UI元素,不应该在生产代码中使用。它们应该被一个自定义的实现所取代。

    例子:

    alert("here!");
    
    confirm("Are you sure?");
    
    prompt("What's your name?", "John Doe");
    
    should be replaced by -
    
    customalert("here!")
    
    customconfirm("Are you sure?")
    
    customprompt("What's your name?", "John Doe")
    
  3. 防止使用new 的副作用

    我们在构造函数中使用new ,以创建一个特定类型的对象,并将该对象存储在一个变量中,例如:

    var car = new Car();
    

    像这样使用new 是没有用的:

    new Car();
    

    在这种情况下,创建的对象会被扔掉,因为它的引用没有存储在任何地方。

安全性

  1. 防止使用eval

    JavaScript的eval() 函数具有潜在的危险性,经常被滥用。在不受信任的代码上使用eval() ,会使程序受到几种不同的注入攻击。在大多数情况下,使用eval() ,可以用更好的、替代性的方法来解决一个问题。

    例子:

    var obj = { x: 'foo' },
      key = 'x',
      value = eval('obj.' + key)
    
  2. 防止使用脚本URLs

    使用javascript。URLs被一些人认为是一种eval 。在javascript中传递的代码。URLs中传递的代码必须被浏览器解析和评估,就像处理eval 一样。此外,组装javascript:URLs(或其他包含源代码的字符串)是一项棘手的任务,很容易出现XSS漏洞。

    例子:

    location.href = 'javascript:void(0)'
    
  3. 防止使用implied-eval

    尝试通过使用setTimeout(),setInterval()execScript() 来消除隐含的eval() 。因此,当这两个函数的第一个参数是字符串时,它将发出警告。

    例子 :

    setTimeout("alert('Hi!');", 100);
    
    setInterval("alert('Hi!');", 100);
    
    execScript("alert('Hi!')");
    
    can be replaced by :
    
    setTimeout(function() {
        alert("Hi!");
    }, 100);
    
    setInterval(function() {
        alert("Hi!");
    }, 100);
    

性能

  1. return,throw,continue, 和break 语句之后检测不可达的代码

    因为return,throw,break, 和continue 语句无条件地退出一个代码块,在它们之后的任何语句都不能被执行。检测并删除它们有助于提高代码的性能。

  2. 检测未使用的变量

    那些在代码中声明了但没有使用的变量,很可能是由于不完整的重构造成的错误。这样的变量会占用代码中的空间并导致混乱。

  3. 检测空的函数声明和块状语句

    空函数会降低可读性,而且最终会占用没有用的空间。空的块状语句,虽然在技术上不是错误,但通常是由于没有完成重构而发生的。它们会在阅读代码时造成混乱,也会影响性能。

    例子:

    function foo() {}
    
    var foo = function () {}
    
    var foo = () => {}
    
    if (foo) {
    }
    
    while (foo) {}