使用 JavaScript

本主题介绍了 Visual Studio Code 支持的一些高级 JavaScript 功能。借助 TypeScript 语言服务,VS Code 不仅可以提供智能代码补全(IntelliSense),还能为 JavaScript 提供类型检查。

IntelliSense

Visual Studio Code 的 JavaScript IntelliSense 提供智能代码补全、参数信息、引用搜索以及许多其他高级语言功能。我们的 JavaScript IntelliSense 由 TypeScript 团队开发的 JavaScript 语言服务提供支持。虽然对于大多数 JavaScript 项目而言,IntelliSense 无需任何配置即可直接工作,但您可以通过 JSDoc 或配置 jsconfig.json 项目来使 IntelliSense 更加强大。

有关 JavaScript IntelliSense 如何工作的详细信息(包括基于类型推断、JSDoc 注释、TypeScript 声明以及混合 JavaScript 和 TypeScript 项目),请参阅 JavaScript 语言服务文档

当类型推断无法提供所需信息时,可以使用 JSDoc 注释显式提供类型信息。本文档描述了当前支持的 JSDoc 注释

除了对象、方法和属性外,JavaScript IntelliSense 窗口还提供文件中符号的基本单词补全。

类型定义(Typings)与自动类型获取

JavaScript 库和框架的 IntelliSense 由 TypeScript 类型声明(typings)文件提供支持。类型声明文件使用 TypeScript 编写,因此它们可以表达参数和函数的数据类型,从而使 VS Code 能够以高性能的方式提供丰富的 IntelliSense 体验。

许多流行的库都附带了类型声明文件,因此您可以自动获得它们的 IntelliSense。对于不包含类型定义的库,VS Code 的自动类型获取(Automatic Type Acquisition)功能会自动为您安装由社区维护的类型声明文件。

自动类型获取需要 npmjs(Node.js 包管理器),它随 Node.js 运行时一同安装。在此图中,您可以看到针对流行 lodash 库的 IntelliSense,包括方法签名、参数信息和方法文档。

lodash typings

对于项目 package.json 中列出的或您导入到 JavaScript 文件中的包,Visual Studio Code 会自动下载并管理其类型声明文件。

{
  "dependencies": {
    "lodash": "^4.17.0"
  }
}

或者,您也可以在 jsconfig.json 中显式列出需要获取类型声明文件的包。

{
  "typeAcquisition": {
    "include": ["jquery"]
  }
}

大多数常见的 JavaScript 库都附带了声明文件,或者提供了可用的类型声明文件。

修复自动类型获取(Automatic Type Acquisition)提示 npm 未安装的警告

自动类型获取使用 npm(Node.js 包管理器)来安装和管理类型声明(typings)文件。为确保自动类型获取正常工作,请首先确保您的机器上已安装 npm。

在终端或命令提示符中运行 npm --version,以快速检查 npm 是否已安装且可用。

npm 随 Node.js 运行时一起安装,可从 Nodejs.org 下载。安装当前的 LTS(长期支持)版本后,npm 可执行文件将默认添加到您的系统路径中。

如果您已安装 npm 但仍看到警告消息,可以通过 js/ts.tsserver.npm.path 设置显式告知 VS Code npm 的安装位置。此项应设置为您机器上 npm 可执行文件的完整路径,且无需与您在工作区中用于管理包的 npm 版本相匹配。js/ts.tsserver.npm.path 需要 TypeScript 2.3.4+ 版本。

例如,在 Windows 上,您可以在 settings.json 文件中添加如下路径:

{
  "js/ts.tsserver.npm.path": "C:\\Program Files\\nodejs\\npm.cmd"
}

JavaScript 项目 (jsconfig.json)

目录中存在 jsconfig.json 文件,即表示该目录是 JavaScript 项目的根目录。jsconfig.json 指定了根文件以及 JavaScript 语言服务所提供语言功能的选项。对于常规设置,不需要 jsconfig.json 文件,但在某些情况下,您需要添加该文件。

  • 并非所有文件都应该包含在您的 JavaScript 项目中(例如,您希望从 IntelliSense 中排除某些文件)。这种情况在前端和后端代码中很常见。
  • 如果您的工作区包含多个项目上下文,则应为每个项目的根文件夹添加一个 jsconfig.json 文件。
  • 您正在使用 TypeScript 编译器向下编译 JavaScript 源代码。

jsconfig.json 的位置

要将代码定义为 JavaScript 项目,请在 JavaScript 代码根目录下创建 jsconfig.json,如下所示。JavaScript 项目应仅包含项目的源文件,不应包含衍生或打包的文件(例如 dist 目录)。

jsconfig setup

在更复杂的项目中,工作区内可能定义了多个 jsconfig.json 文件。这样做的目的是为了让一个项目中的源代码不会出现在另一个项目的 IntelliSense 中。

下图展示了一个包含 clientserver 文件夹的项目,说明了两个独立的 JavaScript 项目

multiple jsconfigs

编写 jsconfig.json

以下是一个简单的 jsconfig.json 文件模板,它将 JavaScript target 定义为 ES6,并使用 exclude 属性排除了 node_modules 文件夹。您可以将此代码复制并粘贴到您的 jsconfig.json 文件中。

{
  "compilerOptions": {
    "module": "CommonJS",
    "target": "ES6"
  },
  "exclude": ["node_modules", "**/node_modules/*"]
}

exclude 属性告诉语言服务哪些文件不属于您的源代码。如果 IntelliSense 速度较慢,请向 exclude 列表中添加文件夹(如果检测到补全速度缓慢,VS Code 会提示您执行此操作)。您应当 exclude 构建过程中生成的文件(例如 dist 目录)。这些文件会导致建议重复显示,并降低 IntelliSense 的速度。

您可以使用 include 属性显式设置项目中的文件。如果没有 include 属性,则默认为包含所在目录及子目录下的所有文件。当指定了 include 属性时,仅包含指定的文件。

以下是一个显式使用 include 属性的示例:

{
  "compilerOptions": {
    "module": "CommonJS",
    "target": "ES6"
  },
  "include": ["src/**/*"]
}

最佳实践(也是最不容易出错的方法)是使用带有单个 src 文件夹的 include 属性。请注意,excludeinclude 中的文件路径是相对于 jsconfig.json 所在位置的。

有关更多信息,请参阅完整的 jsconfig.json 文档

迁移到 TypeScript

可以拥有混合的 TypeScript 和 JavaScript 项目。要开始迁移到 TypeScript,请将您的 jsconfig.json 文件重命名为 tsconfig.json,并将 allowJs 属性设置为 true。有关更多信息,请参阅从 JavaScript 迁移

注意: jsconfig.jsontsconfig.json 文件相同,只是默认将 allowJs 设置为 true。请参阅此处有关 tsconfig.json 的文档以查看其他可用选项。

JavaScript 类型检查

VS Code 允许您在常规 JavaScript 文件中利用 TypeScript 的部分高级类型检查和错误报告功能。这是捕获常见编程错误的绝佳方法。这些类型检查还为 JavaScript 启用了许多令人兴奋的“快速修复”(Quick Fixes),包括添加缺失的导入添加缺失的属性

Using type checking and Quick Fixes in a JavaScript file

TypeScript 可以像在 .ts 文件中一样在 .js 文件中推断类型。当无法推断类型时,可以使用 JSDoc 注释来指定它们。您可以在 类型检查 JavaScript 文件 中阅读更多关于 TypeScript 如何使用 JSDoc 进行 JavaScript 类型检查的内容。

JavaScript 的类型检查是可选的。现有的 JavaScript 验证工具(如 ESLint)可以与新的内置类型检查功能结合使用。

根据您的需要,可以通过几种不同的方式开始类型检查。

按文件

在 JavaScript 文件中启用类型检查的最简单方法是在文件顶部添加 // @ts-check

// @ts-check
let itsAsEasyAs = 'abc';
itsAsEasyAs = 123; // Error: Type '123' is not assignable to type 'string'

如果您只是想在少数文件中尝试类型检查,而不希望为整个代码库启用它,使用 // @ts-check 是一个很好的方法。

使用设置

要为所有 JavaScript 文件启用类型检查且无需更改任何代码,只需在您的工作区或用户设置中添加 "js/ts.implicitProjectConfig.checkJs": true 即可。这将为所有不属于 jsconfig.jsontsconfig.json 项目的 JavaScript 文件启用类型检查。

您可以使用文件顶部的 // @ts-nocheck 注释来选择单个文件不进行类型检查。

// @ts-nocheck
let easy = 'abc';
easy = 123; // no error

您还可以使用错误行上一行的 // @ts-ignore 注释来禁用 JavaScript 文件中的单个错误。

let easy = 'abc';
// @ts-ignore
easy = 123; // no error

使用 jsconfig 或 tsconfig

要为属于 jsconfig.jsontsconfig.json 的 JavaScript 文件启用类型检查,请在项目的编译器选项中添加 "checkJs": true

jsconfig.json:

{
  "compilerOptions": {
    "checkJs": true
  },
  "exclude": ["node_modules", "**/node_modules/*"]
}

tsconfig.json:

{
  "compilerOptions": {
    "allowJs": true,
    "checkJs": true
  },
  "exclude": ["node_modules", "**/node_modules/*"]
}

这将为项目中的所有 JavaScript 文件启用类型检查。您可以使用 // @ts-nocheck 按文件禁用类型检查。

JavaScript 类型检查需要 TypeScript 2.3+ 版本。如果您不确定当前工作区中激活的 TypeScript 版本,请运行TypeScript: Select TypeScript Version 命令进行检查。您必须在编辑器中打开一个 .js/.ts 文件才能运行此命令。如果您打开了 TypeScript 文件,版本信息会显示在右下角。

全局变量与类型检查

假设您正在处理使用全局变量或非标准 DOM API 的遗留 JavaScript 代码:

window.onload = function() {
  if (window.webkitNotifications.requestPermission() === CAN_NOTIFY) {
    window.webkitNotifications.createNotification(null, 'Woof!', '🐶').show();
  } else {
    alert('Could not notify');
  }
};

如果您尝试对上述代码使用 // @ts-check,将会看到许多关于全局变量使用的错误:

  1. 第 2 行 - Property 'webkitNotifications' does not exist on type 'Window'.(属性 'webkitNotifications' 在类型 'Window' 上不存在。)
  2. 第 2 行 - Cannot find name 'CAN_NOTIFY'.(找不到名称 'CAN_NOTIFY'。)
  3. 第 3 行 - Property 'webkitNotifications' does not exist on type 'Window'.

如果您想继续使用 // @ts-check,但确信这些不是应用程序的实际问题,则需要让 TypeScript 了解这些全局变量。

首先,在项目根目录下创建一个 jsconfig.json

{
  "compilerOptions": {},
  "exclude": ["node_modules", "**/node_modules/*"]
}

然后重新加载 VS Code 以确保更改生效。jsconfig.json 的存在让 TypeScript 知道您的 JavaScript 文件是大型项目的一部分。

现在在工作区的某个位置创建一个 globals.d.ts 文件:

interface Window {
  webkitNotifications: any;
}

declare var CAN_NOTIFY: number;

d.ts 文件是类型声明文件。在此例中,globals.d.ts 让 TypeScript 知道存在一个全局变量 CAN_NOTIFY,并且 window 上存在一个 webkitNotifications 属性。您可以在 TypeScript 文档 中阅读更多关于编写 d.ts 的内容。d.ts 文件不会更改 JavaScript 的评估方式,它们仅用于提供更好的 JavaScript 语言支持。

使用任务

使用 TypeScript 编译器

TypeScript 的核心功能之一是能够使用最新的 JavaScript 语言特性,并生成可以在尚不支持这些新特性的 JavaScript 运行时中执行的代码。由于 JavaScript 使用相同的语言服务,现在它也可以利用这一功能。

TypeScript 编译器 tsc 可以将 JavaScript 文件从 ES6 向下编译(down-level compile)到其他语言级别。使用所需选项配置 jsconfig.json,然后使用 -p 参数让 tsc 使用您的 jsconfig.json 文件,例如 tsc -p jsconfig.json 进行向下编译。

jsconfig 文档 中阅读更多关于向下编译的编译器选项信息。

运行 Babel

Babel 转译器可以将 ES6 文件转换为带有 Source Maps 的可读 ES5 JavaScript。通过将以下配置添加到您的 tasks.json 文件(位于工作区的 .vscode 文件夹下),您可以轻松地将 Babel 集成到您的工作流程中。group 设置将此任务设为默认的 Tasks: Run Build Task(运行构建任务)手势。isBackground 告诉 VS Code 在后台持续运行此任务。要了解更多信息,请前往 任务 (Tasks)

{
  "version": "2.0.0",
  "tasks": [
    {
      "label": "watch",
      "command": "${workspaceFolder}/node_modules/.bin/babel",
      "args": ["src", "--out-dir", "lib", "-w", "--source-maps"],
      "type": "shell",
      "group": { "kind": "build", "isDefault": true },
      "isBackground": true
    }
  ]
}

添加配置后,您可以使用 ⇧⌘B (Windows, Linux Ctrl+Shift+B) (运行构建任务) 命令启动 Babel,它会将 src 目录中的所有文件编译到 lib 目录中。

提示: 有关 Babel CLI 的帮助,请参阅 使用 Babel 中的说明。上面的示例使用了 CLI 选项。

禁用 JavaScript 支持

如果您更喜欢使用其他 JavaScript 工具(如 Flow)支持的 JavaScript 语言功能,则可以禁用 VS Code 的内置 JavaScript 支持。您可以通过禁用内置的 TypeScript 语言扩展 TypeScript and JavaScript Language Features (vscode.typescript-language-features) 来实现这一点,该扩展同时也提供了 JavaScript 语言支持。

要禁用 JavaScript/TypeScript 支持,请转到扩展视图 (⇧⌘X (Windows, Linux Ctrl+Shift+X)) 并筛选内置扩展(在 ... 更多操作 下拉菜单中选择 Show Built-in Extensions),然后输入 'typescript'。选择 TypeScript and JavaScript Language Features 扩展并按下 Disable(禁用)按钮。VS Code 的内置扩展无法卸载,只能禁用,并且可以随时重新启用。

TypeScript and JavaScript Language Features extension

部分 IntelliSense 模式

VS Code 尝试为 JavaScript 和 TypeScript 提供项目级的 IntelliSense,这使得诸如自动导入和转到定义(Go to Definition)等功能成为可能。但是,在某些情况下,VS Code 仅限于处理您当前打开的文件,无法加载构成您 JavaScript 或 TypeScript 项目的其他文件。

这种情况可能发生在以下几种实例中:

  • 您正在 vscode.devgithub.dev 上处理 JavaScript 或 TypeScript 代码,并且 VS Code 在浏览器中运行。
  • 您从虚拟文件系统打开文件(例如使用 GitHub Repositories 扩展时)。
  • 项目正在加载中。加载完成后,您将开始获得该项目的项目级 IntelliSense。

在这些情况下,VS Code 的 IntelliSense 将以部分模式(partial mode)运行。部分模式会尽最大努力为您打开的任何 JavaScript 或 TypeScript 文件提供 IntelliSense,但功能受限,无法提供任何跨文件的 IntelliSense 功能。

哪些功能会受到影响?

以下是不完整的功能列表,它们在部分模式下被禁用或功能受到限制:

  • 所有打开的文件都被视为单个项目的一部分。
  • 来自 jsconfigtsconfig 的配置选项(例如 target)不被遵循。
  • 仅报告语法错误。语义错误(如访问未知属性或向函数传递错误的类型)不会被报告。
  • 语义错误的“快速修复”功能被禁用。
  • 符号只能在当前文件内解析。从其他文件导入的任何符号都将被视为 any 类型。
  • 转到定义查找所有引用等命令只能在打开的文件中工作,而不能跨整个项目工作。这也意味着您在 node_modules 下安装的任何包中的符号将无法解析。
  • 工作区符号搜索将仅包含当前打开文件中的符号。
  • 自动导入功能被禁用。
  • 重命名功能被禁用。
  • 许多重构功能被禁用。

vscode.devgithub.dev 上还有一些额外的功能被禁用:

检查是否处于部分模式

要检查当前文件是使用部分模式 IntelliSense 还是项目级 IntelliSense,请将鼠标悬停在状态栏中的 JavaScriptTypeScript 语言状态项上。

Partial mode status item

如果当前文件处于部分模式,状态项将显示 Partial mode(部分模式)。

© . This site is unofficial and not affiliated with Microsoft.