# @forbeslindesay/jsdom 中文文档

规范地址：https://npmcn.com/package/%40forbeslindesay/jsdom/

版本：11\.1\.9
npm 元数据更新时间：2022-06-12T18:02:48.889Z
中文译文更新时间：2026-11-15T17:44:37.089Z
软件包许可：MIT

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40forbeslindesay/jsdom
原文对照：https://npmcn.com/package/%40forbeslindesay/jsdom/?lang=original
项目主页：https://github.com/tmpvar/jsdom#readme
源码仓库：https://github.com/tmpvar/jsdom

## 关键信息（来自 npm 元数据）

- 模块格式：CommonJS
- TypeScript 类型：未声明
- 运行依赖：21 个
- 首次发布：2017-07-07T08:11:54.539Z
- 最新版本发布：2017-07-09T01:41:30.879Z
- 近 30 天下载量：2018（2026-10-16 至 2026-11-14，npm 官方下载统计）
- 已发布版本数：10（近 12 个月 0 个）

## 中文简介

JavaScript 许多网络标准的执行

## 安装

```sh
npm install @forbeslindesay/jsdom
```

也可以使用：`pnpm add @forbeslindesay/jsdom`、`yarn add @forbeslindesay/jsdom`、`bun add @forbeslindesay/jsdom`

## README

# 日记

jsdom是许多网络标准的纯Java脚本执行,尤其是WHWG [管理部](https://dom.spec.whatwg.org/) 财务报告和审定财务报表 [HTML 语言](https://html.spec.whatwg.org/multipage/) 标准,与Node.js一起使用. 一般来说,该项目的目标是模仿足够多的网络浏览器子集,用于测试和刮去真实世界的网络应用.

Jsdom的最新版本需要Node.js v6或更新. (v10下方的jsdom版本仍然与Node.js v4合作,但并不支持

截至v10,jsdom有一个新的API(下面记载). 原有的API目前仍然得到支持; [见文件](https://npmcn.com/package/%40forbeslindesay/jsdom/lib/old-api.md) 详细情况.

## 基本用途

```js
const jsdom = require("jsdom");
const { JSDOM } = jsdom;
```

要使用jsdom, 您将主要使用 `JSDOM` 构造器,是 jsdom 主模块的命名导出 。 传出构造器一串. 你会回来的 `JSDOM` 对象,它具有一些有用的属性,特别是 `window`数字 :

```js
const dom = new JSDOM(`<!DOCTYPE html><p>Hello world</p>`);
console.log(dom.window.document.querySelector("p").textContent); // "Hello world"
```

(注意jsdom将解析您通过的HTML,就像浏览器一样,包括隐含的) `<html>`, (中文(简体) ), `<head>`,以及 `<body>` 标记。 )

生成的对象是 `JSDOM` 类,其中包含若干有用的属性和方法,除此之外 `window`。一般来说,它可以用来从“外部”来进行jsdom, 做一些与普通的DOM API不可能做的事情。 对于简单的案例,如果您不需要任何这种功能,我们建议一个编码模式,比如:

```js
const { window } = new JSDOM(`...`);
// or even
const { document } = (new JSDOM(`...`)).window;
```

关于你所能做的每件事的完整文档 `JSDOM` 分类如下,在一节中 "`JSDOM` 对象 API".

## 自定义jsdom

这个 `JSDOM` 构造器接受第二个参数,可以用以下方式自定义您的jsdom .

### 简单选项

```js
const dom = new JSDOM(``, {
  url: "https://example.org/",
  referrer: "https://example.com/",
  contentType: "text/html",
  userAgent: "Mellblomenator/9000",
  includeNodeLocations: true
});
```

-   `url` 设置返回的值 `window.location`, (中文(简体) ), `document.URL`,以及 `document.documentURI`,并影响诸如文档中相对URL的解析度,以及获取子资源时使用的同源限制和裁判员。 默认为 `"about:blank"`。 。 。 .
-   `referrer` 只影响从 `document.referrer`。它默认为无引用者(它反映为空字符串).
-   `contentType` 影响从 `document.contentType`,以及文档是如何解析的:作为 HTML 或 XML 。 非数值 `"text/html"` 或一个 [XML MIME 类型](https://html.spec.whatwg.org/multipage/infrastructure.html#xml-mime-type) 会投出。 默认为 `"text/html"`。 。 。 .
-   `userAgent` 影响从 `navigator.userAgent`,以及 `User-Agent` 获取子资源时发送了标题 。 默认为 `` `Mozilla/5.0 (${process.platform}) AppleWebKit/537.36 (KHTML, like Gecko) jsdom/${jsdomVersion}` ``。 。 。 .
-   `includeNodeLocations` 保存 HTML 解析器生成的位置信息,允许您用 `nodeLocation()` 方法(见下文)。 默认为 `false` 以给出最佳性能,不能使用 XML 内容类型,因为我们的 XML 解析器不支持位置信息.

注意两者 `url` 财务报告和审定财务报表 `referrer` 在他们使用之前就被卡通化了, 所以,例如,如果你通过 `"https:example.com"`,jsdom会解释,就像你给了 `"https://example.com/"`。如果通过一个无法解析的 URL,则该调用会发出。 (按 [URL 标准](http://url.spec.whatwg.org/). ) (中文(简体) )

### 执行脚本

jsdom最强大的能力是可以在jsdom内部执行脚本. 这些脚本可以修改页面内容并访问所有网络平台APIS jsdom执行.

然而,在处理不可信的内容时,这也非常危险。 jsdom 沙盒不是愚蠢的, 代码运行在 DOM 内部 `<script>`s可以,如果它足够努力, 获得进入节点环境, 从而进入你的机器。 因此,HTML中嵌入的脚本执行能力默认被禁用:

```js
const dom = new JSDOM(`<body>
  <script>document.body.appendChild(document.createElement("hr"));</script>
</body>`);

// The script will not be executed, by default:
dom.window.document.body.children.length === 1;
```

要启用页面中的执行脚本, 您可以使用 `runScripts: "dangerously"` 选项 :

```js
const dom = new JSDOM(`<body>
  <script>document.body.appendChild(document.createElement("hr"));</script>
</body>`, { runScripts: "dangerously" });

// The script will be executed and modify the DOM:
dom.window.document.body.children.length === 2;
```

我们再次强调,只有在喂养Jsdom代码时才使用这个代码,你知道是安全的。 如果您在任意用户提供代码上使用,或者在互联网上使用代码,则您正在有效运行不可信Node.js代码,您的机器可能会被损坏.

注意事件处理器属性, 如 `<div onclick="">`,除非 `runScripts` 设置为 `"dangerously"`. (然而,事件处理器 _属性_一样 `div.onclick = ...`,将不管 `runScripts`. ) (中文(简体) )

如果你只是试图从外部执行脚本,而不是让 `<script>` 元素(和内置事件处理器)从内部运行,您可以使用 `runScripts: "outside-only"` 选项,允许 `window.eval`数字 :

```js
const window = (new JSDOM(``, { runScripts: "outside-only" })).window;

window.eval(`document.body.innerHTML = "<p>Hello, world!</p>";`);
window.document.body.children.length === 1;
```

由于性能原因,它默认关闭,但安全启用.

请注意,我们强烈建议不要试图通过将jsdom和Node全球环境(例如通过做)混合起来来"执行脚本" `global.window = dom.window`),然后在节点全球环境中执行脚本或测试代码. 相反,你应该像浏览器一样对待jsdom,运行所有需要访问jsdom环境中的DOM的脚本和测试,使用 `window.eval` 或者说 `runScripts: "dangerously"`。例如,这可能需要创建一个浏览器捆绑以作为执行 `<script>` 元素 - 就像你在浏览器中一样.

最后,对于高级用途,您可以使用 `dom.runVMScript(script)` 方法,见下文.

### 正在装入子资源

默认情况下, jsdom 将不会装入任何子资源, 如脚本, 样式表, 图像, 或 iframes 。 如果你希望Jsdom 装载这样的资源,你可以通过 `resources: "usable"` 选项,将载入所有可用的资源。 它们是:

-   框架和iframes,通过 `<frame>` 财务报告和审定财务报表 `<iframe>`
-   样式表,通过 `<link rel="stylesheet">`
-   脚本,通过 `<script>`,但只有在 `runScripts: "dangerously"` 还设置了
-   图像,通过 `<img>`,但只有在 `canvas` (或 `canvas-prebuilt`npm 软件包也被安装(见下文"Canvas Support")

今后我们计划通过这个选项对资源加载进行更多的定制,但目前默认和 `"usable"` 选项是提供的两种模式.

### 虚拟控制台

和网页浏览器一样,jsdom也有"主机"的概念. 这既记录了从页面直接发送的信息、文件内执行的脚本,也记录了jsdom执行本身的信息。 我们称用户控制控制控制台为"虚拟控制台",以区别于节点.js `console` API和内页 `window.console` API (英语).

默认情况下 `JSDOM` 构造器将返回一个带有虚拟控制台的实例,该虚拟控制台将把全部输出转发到节点.js控制台. 要创建自己的虚拟控制台并将其传递到jsdom,您可以通过做来推翻这个默认

```js
const virtualConsole = new jsdom.VirtualConsole();
const dom = new JSDOM(``, { virtualConsole });
```

像这样的代码将创建一个没有行为的虚拟控制台. 您可以通过为所有可能的控制台方法添加事件听众来给出行为 :

```js
virtualConsole.on("error", () => { ... });
virtualConsole.on("warn", () => { ... });
virtualConsole.on("info", () => { ... });
virtualConsole.on("dir", () => { ... });
// ... etc. See https://console.spec.whatwg.org/#logging
```

(注意,也许最好设置这些活动的听众) _在此之前_ 电话 `new JSDOM()`,因为解析时可能会出错或引用控制台脚本. )

如果您只是想要将虚拟控制台的输出重定向到另一个控制台, 就像默认的节点. js 一样, 您可以这样做

```js
virtualConsole.sendTo(console);
```

还有一件特别的事, `"jsdomError"`,它会用出错的物体来报告jsdom本身的错误。 这类似于错误消息常常出现在网页浏览器控制台中,即使它们不是由启动的 `console.error`。到目前为止,以下错误是用这种方式输出的:

-   装入或解析子资源出错( 脚本、 样式表、 框架和 iframe)
-   未由窗口处理的脚本执行错误 `onerror` 返回的事件处理器 `true` 或打电话 `event.preventDefault()`
-   调用方法造成的未执行错误,例如 `window.alert`,jsdom不执行,但无论如何为网络兼容性安装

如果你在用的话 `sendTo(c)` 发送错误到 `c`,默认情况下将调用 `console.error` 信息从 `"jsdomError"` 事件。 如果你愿意保持一个严格的一对一 事件映射 方法调用,也许处理 `"jsdomError"`自己一个人,你就可以做

```js
virtualConsole.sendTo(c, { omitJSDOMErrors: true });
```

### 饼干罐

像网页浏览器一样,jsdom有饼干罐的概念,存储了HTTP饼干. 在与文档相同的域上拥有URL且不只标有 HTTP 的饼干可以通过 `document.cookie` API (英语). 此外,饼干罐中的所有饼干都会影响子资源的取取取.

默认情况下 `JSDOM` 构造器会用空饼干罐返回一个实例 。 要创建自己的饼干罐并将其传递到jsdom,你可以通过做来克服这个默认

```js
const cookieJar = new jsdom.CookieJar(store, options);
const dom = new JSDOM(``, { cookieJar });
```

如果您想要在多个jsdoms中共享同样的饼干罐, 或提前将饼干罐装入具有一定值的质素, 这一点就大有用处 .

Cookie罐头由 [硬饼干](https://www.npmjs.com/package/tough-cookie) 软件包。 这个 `jsdom.CookieJar` 构造器是硬饼干罐子的子类,默认是设置 `looseMode: true` 选项,因为 [更匹配浏览器的表现](https://github.com/whatwg/html/issues/804)。如果你想使用硬饼干的公用事业 和课程你自己,你可以使用 `jsdom.toughCookie` 模块导出以获取使用 jsdom 包装的硬饼干模块实例.

### 解析前的干涉

jsdom允许您很早就介入 jsdom 的创建: `Window` 财务报告和审定财务报表 `Document` 对象被创建,但在解析出 HTML 以将文档填入节点之前:

```js
const dom = new JSDOM(`<p>Hello</p>`, {
  beforeParse(window) {
    window.document.childNodes.length === 0;
    window.someCoolAPI = () => { /* ... */ };
  }
});
```

如果您想要以某种方式修改环境, 这尤其有用, 例如为网络平台 APIS jsdom 添加 shims 不支持 .

## `JSDOM` 对象 API

一旦你建造了一个 `JSDOM` 对象,它将具有以下有用的能力:

### 属性

财产 `window` 获取 `Window` 为您创建的对象.

属性 `virtualConsole` 财务报告和审定财务报表 `cookieJar` 反映您通过的选项, 或为您创建的默认选项, 如果这些选项没有被输入的话.

### 将文档序列化 `serialize()`

这个 `serialize()` 方法将返回 [HTML 序列化](https://html.spec.whatwg.org/#html-fragment-serialisation-algorithm) 包括文件类型:

```js
const dom = new JSDOM(`<!DOCTYPE html>hello`);

dom.serialize() === "<!DOCTYPE html><html><head></head><body>hello</body></html>";

// Contrast with:
dom.window.document.documentElement.outerHTML === "<html><head></head><body>hello</body></html>";
```

### 获取节点的源位置 `nodeLocation(node)`

这个 `nodeLocation()` 方法将查找源文档中的 DOM 节点,返回 [解析5 位置信息](https://www.npmjs.com/package/parse5#options-locationinfo) 用于节点:

```js
const dom = new JSDOM(
  `<p>Hello
    <img src="foo.jpg">
  </p>`,
  { includeNodeLocations: true }
);

const document = dom.window.document;
const bodyEl = document.body; // implicitly created
const pEl = document.querySelector("p");
const textNode = pEl.firstChild;
const imgEl = document.querySelector("img");

console.log(dom.nodeLocation(bodyEl));   // null; it's not in the source
console.log(dom.nodeLocation(pEl));      // { startOffset: 0, endOffset: 39, startTag: ..., endTag: ... }
console.log(dom.nodeLocation(textNode)); // { startOffset: 3, endOffset: 13 }
console.log(dom.nodeLocation(imgEl));    // { startOffset: 13, endOffset: 32 }
```

注意此特性只有在您设置了 `includeNodeLocations` 选项;由于性能原因,节点位置默认关闭.

### 运行 vm 创建脚本 `runVMScript(script)`

内置 `vm` 模块允许您创建 `Script` 实例,可以提前编译,然后在给定的"VM上下文"上多次运行. 在幕后,一个jsdom `Window` 这的确是一个自愿参与的背景。 为了获得这种能力 `runVMScript()` 方法 :

```js
const { Script } = require("vm");

const dom = new JSDOM(``, { runScripts: "outside-only" });
const s = new Script(`
  if (!this.ran) {
    this.ran = 0;
  }

  ++this.ran;
`);

dom.runVMScript(s);
dom.runVMScript(s);
dom.runVMScript(s);

dom.window.ran === 3;
```

这功能有些先进,我们建议坚持使用普通的DOM API(例如: `window.eval()` 或者说 `document.createElement("script")`除非你有非常具体的需求.

### 将jsdom重新配置为 `reconfigure(settings)`

这个 `top` 属性在 `window` 标记 `[Unforgeable]` 在 spec中,意思是它是一个不可定义的自有财产,因此不能被运行在jsdom内部的普通代码所压倒或阴影,甚至使用 `Object.defineProperty`。 。 。 .

同样,目前jsdom不处理导航(例如设置) `window.location.href === "https://example.com/"`);这样做将使虚拟控制台发出一个 `"jsdomError"` 解释这一特性没有实施,没有什么变化:没有新的 `Window` 或者说 `Document` 对象和现有的 `window`是因为 `location` 对象仍然具有所有相同的属性值.

然而,如果你从窗外行动,例如在某些创建jsdoms的测试框架中,可以使用特制来覆盖其中的一种或两种 `reconfigure()` 方法 :

```js
const dom = new JSDOM();

dom.window.top === dom.window;
dom.window.location.href === "about:blank";

dom.reconfigure({ windowTop: myFakeTopForTesting, url: "https://example.com/" });

dom.window.top === myFakeTopForTesting;
dom.window.location.href === "https://example.com/";
```

注意更改 jsdom 的 URL 会影响返回当前文档 URL 的所有 API, 例如 `window.location`, (中文(简体) ), `document.URL`,以及 `document.documentURI`,以及文档中相对URL的解析,以及在获取子资源时使用的同源检查和裁判。 但是,它不会对该URL的内容进行导航;DOM的内容将保持不变,没有新的实例显示 `Window`, (中文(简体) ), `Document`等将创建.

## 方便性 APIs

### `fromURL()`

计外 `JSDOM` 建构器本身, jsdom 提供了从 URL 构建 jsdom 的许诺回放厂法 :

```js
JSDOM.fromURL("https://example.com/", options).then(dom => {
  console.log(dom.serialize());
});
```

回来的诺言将以一个 `JSDOM` 如果 URL 有效且请求成功。 任何改道都将被跟踪到最终目的地.

向 `fromURL()` 与向难民署提供的类似 `JSDOM` (a) 具有下列额外限制和后果的构造器:

-   这个 `url` 财务报告和审定财务报表 `contentType` 无法提供选项.
-   这个 `referrer` 选项用作 HTTP `Referer` 请求初始请求标题.
-   这个 `userAgent` 选项用作 HTTP `User-Agent` 请求任何请求的页眉.
-   由此而来jsdom的URL,内容类型,以及参考者由响应决定.
-   通过 HTTP 设置任何饼干 `Set-Cookie` 响应头被存储在jsdom的饼干罐. 类似地,任何已经在供应的饼干罐中的饼干都会作为HTTP发送 `Cookie` 请求标题.

初始请求并不是无限定制的 尽可能在类似包中 [请求](https://www.npmjs.com/package/request)· ; `fromURL()` 目的是为大多数案件提供方便。 需要更多控制初始请求的,应当自行执行,然后使用 `JSDOM` 人工构造器.

### `fromFile()`

类似 `fromURL()`,jsdom 也提供了一个 `fromFile()` 从文件名构建 jsdom 的工厂方法 :

```js
JSDOM.fromFile("stuff.html", options).then(dom => {
  console.log(dom.serialize());
});
```

回来的诺言将以一个 `JSDOM` 实例,如果可以打开给定文件。 和通常在Node.js APIs中一样,文件名是相对于当前工作目录给出的.

向 `fromFile()` 与向难民署提供的类似 `JSDOM` 构造器,并附加下列默认值:

-   这个 `url` 选项将默认为对应给定文件名的文件 URL,而不是 `"about:blank"`。 。 。 .
-   这个 `contentType` 选项默认为 `"application/xhtml+xml"` 如果给定的文件名以 `.xhtml` 或者说 `.xml`;否则将继续默认为 `"text/html"`。 。 。 .

### `fragment()`

最简单的是,你可能不需要一个整体 `JSDOM` 拥有一切相关权力 你可能甚至不需要一个 `Window` 或者说 `Document`相反,你只需要解析一些 HTML,然后得到一个您可以操纵的 DOM 对象 。 为此,我们有 `fragment()`,从而创建一个 `DocumentFragment` 从给定字符串中:

```js
const frag = JSDOM.fragment(`<p>Hello</p><p><strong>Hi!</strong>`);

frag.childNodes.length === 2;
frag.querySelector("strong").textContent = "Why hello there!";
// etc.
```

给 `frag` 是一个 [`DocumentFragment`](https://developer.mozilla.org/en-US/docs/Web/API/DocumentFragment) 实例,其内容是通过解析提供的字符串创建的。 解析是使用 `<template>` 元素,所以您可以包含那里的任何元素(包括那些有奇怪解析规则的元素,例如: `<td>`) (中文(简体) ).

所有援引 `framgment()` 工厂结果 `DocumentFragment`s,共用同一个所有者 `Document` 财务报告和审定财务报表 `Window`。这允许许多电话 `fragment()` 没有额外的间接费用。 但这也意味着呼吁 `fragment()` 无法以任何选项定制 .

注意序列化并不容易 `DocumentFragment`满地都是这样 `JSDOM` 对象。 如果你需要序列化你的DOM, 你也许应该使用 `JSDOM` 更直接的构造器。 但对于包含单一元素的碎片的特殊情况,通过正常方式相当容易做到:

```js
const frag = JSDOM.fragment(`<p>Hello</p>`);
console.log(frag.firstChild.outerHTML); // logs "<p>Hello</p>"
```

## 其他值得注意的特征

### 屏幕支持

jsdom 包括对使用 [`canvas`](https://www.npmjs.com/package/canvas) 或者说 [`canvas-prebuilt`](https://npmjs.org/package/canvas-prebuilt) 要扩展任意 `<canvas>` 包含 API 的元素。 要做到这一点,你需要包括 `canvas` 作为项目中的依赖者 作为同行 `jsdom`如果jsdom能够找到 `canvas` 包,它会使用它, 但如果它不在场, 那么 `<canvas>` 元素将像 `<div>`编号.

### 编码嗅觉

除了提供串 `JSDOM` 也可以以节点.js的形式提供二进制数据 [`Buffer`](https://nodejs.org/docs/latest/api/buffer.html) 或标准 JavaScript 二进制数据类型 `ArrayBuffer`, (中文(简体) ), `Uint8Array`, (中文(简体) ), `DataView`等 (中文(简体) ). 完成后,Jsdom会 [嗅出编码](https://html.spec.whatwg.org/multipage/syntax.html#encoding-sniffing-algorithm) 从提供的字节中扫描 `<meta charset>` 标记就像浏览器一样.

这种编码嗅觉也适用于 `JSDOM.fromFile()` 财务报告和审定财务报表 `JSDOM.fromURL()`在后一种情况下,如浏览器中,任意 `Content-Type` 随答复而发送的信头将优先处理.

### 关闭一个jsdom

Jsdom中的计时器( 由 `window.setTimeout()` 或者说 `window.setInterval()`)顾名思义,将来会在窗口上下文中执行代码. 由于未来没有方法执行代码而不保持进程的生命力,杰出的jsdom定时器将保持你的Node.js进程的生命力. 同样,由于无法在对象上下文中执行代码而不使该对象存活,未完成的jsdom定时器会阻止其预定的窗口的垃圾收集.

如果您想要确定关闭 Jsdom 窗口, 请使用 `window.close()`,它将终止所有运行的定时器(并删除窗口和文档上的任何事件听众).

### 在网页浏览器内运行jsdom

jsdom 支持在网页浏览器内运行,使用 [浏览器](https://browserify.org/)。也就是说,在网页浏览器内,您可以使用浏览器化的jsdom来创建一套完全自成一体的平版JavaScript对象,这些对象看起来和浏览器现有的DOM对象很像,同时完全独立于它们. "虚拟DOM",真的!

jsdom的首要目标仍然是Node.js,因此我们使用仅存在于最近Node.js版本(即Node.js v6+)中的语言特征. 因此,更古老的浏览器很可能无法工作. (即使转接也无济于事:我们计划使用) `Proxy`s 在整个jsdom v10.x.过程中广泛存在.)

值得注意的是,jsdom在网络工人内部运作良好。 原始贡献者, [@ 劳伦斯:](https://github.com/lawnsea/)使这一切成为可能 [发表论文](https://pdfs.semanticscholar.org/47f0/6bb6607a975500a30e9e52d7c9fbc0034e27.pdf) 关于他利用这种能力的项目.

在网页浏览器内运行 jsdom 时, 并非一切都完美 。 这有时是因为根本的限制(比如没有文件系统访问),但有时只是因为我们没有花足够的时间做适当的小调. 虫子报告当然是值得欢迎的.

## 洞穴

### 同步装入脚本

人们在使用jsdom时经常会遇到同步脚本加载的困难. 许多页面同步地加载脚本,但无法分辨何时完成,因此当是运行您的代码并检查由此产生的DOM结构的好时机时. 这是一个根本性的限制;我们无法预测网页上的脚本会做什么,因此无法在装入更多脚本时告诉你.

这可以有几种方式。 最好的方法是,如果控制相关页面,则使用脚本加载器给出的任何机制,在加载完成后进行检测. 例如,如果使用像RequestJS这样的模块加载器,代码可能看起来像:

```js
// On the Node.js side:
const window = (new JSDOM(...)).window;
window.onModulesLoaded = () => {
  console.log("ready to roll!");
};
```

```html
<!-- Inside the HTML you supply to jsdom -->
<script>
requirejs(["entry-module"], () => {
  window.onModulesLoaded();
});
</script>
```

如果您不控制页面, 您可以尝试投票等工作方式.

详细情况,请参见下文讨论 [640号](https://github.com/tmpvar/jsdom/issues/640)特别是 [@ matthewkastor (英语)](https://github.com/matthewkastor)是因为 [深刻的评论](https://github.com/tmpvar/jsdom/issues/640#issuecomment-22216965)。 。 。 .

### 共用建筑工和原型机

目前,对于大多数网络平台API,jsdom在多个看起来独立的jsdom之间共享相同的类定义. 这意味着,例如,以下情况可能发生:

```js
const dom1 = new JSDOM();
const dom2 = new JSDOM();

dom1.window.Element.prototype.expando = "blah";
console.log(dom2.window.document.createElement("frameset").expando); // logs "blah"
```

这主要是出于性能和内存的原因:在网络平台上创建所有众多课程的单独拷贝,每次我们创建jsdom,都会相当昂贵.

然而,我们仍有兴趣有一天提供一种选择,以创造出一种“独立”的jsdom,以牺牲某种表演.

### 新API中缺失的特性

相较于从v9.x及之前的旧jsdom API,新API明显缺失了对资源负载的精度控制. 以前版本的jsdom允许您设置在请求时使用的选项(既用于初始请求,也用于旧的等同请求) `JSDOM.fromURL()`,并用于次级资源请求)。 它们也允许您控制哪些子资源被请求并应用到主文档中,以便您可以例如下载样式表而不是脚本. 最后,它们提供了一种自定义的资源加载器,可以让你拦截任何发出的请求,并以完全合成的响应来实现.

这些功能还没有出现在新的jsdom API中,尽管我们希望很快再添加回来! 不幸的是,这要求以合理的方式开展体面的幕后工作.

在此期间,请随意使用旧的jsdom API来获取此功能. 它得到支持和维护,尽管它不会获得新的特征。 文件见 [自由/旧阿皮德](https://npmcn.com/package/%40forbeslindesay/jsdom/lib/old-api.md)。 。 。 .

### 未执行的网络平台部分

虽然我们喜欢在jsdom中添加新的功能并不断更新最新的网页规格,但它有许多缺失的API. 请自由提出一个问题 任何缺失, 但我们是一个小而繁忙的团队, 所以拉请求可能更好.

除了我们还没有达到的特征外, 有两个主要的特征 目前不在jsdom的范围。 它们是:

-   **导航**: 单击链接或指定时更改全局对象和所有其他对象的能力 `location.href` 或类似.
-   **版式**: 能够计算由于CSS而将哪些元素直观地布置出来,而CSS会影响各种方法,例如: `getBoundingClientRects()` 或类似属性 `offsetTop`。 。 。 .

目前jsdom对这些功能的某些方面有假行为,例如发送"未执行" `"jsdomError"` ,或返回许多布局相关属性的零。 通常你可以围绕代码中的这些限制工作,例如创建新的 `JSDOM` 在爬行时,或使用 `Object.defineProperty()` 以改变各种布局相关的获取器和方法返回的内容.

注意同一空间中的其他工具,如PhantomJS,确实支持这些特性. 维基百科中的相关条目: 克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克 [jsdom对幽灵JS](https://github.com/tmpvar/jsdom/wiki/jsdom-vs.-PhantomJS)。 。 。 .

## 获得帮助

如果您需要Jsdom的帮助,请随意使用下列任何场所:

-   这个 [邮件列表](http://groups.google.com/group/jsdom) (最适合"我如何"的问题)
-   这个 [问题跟踪器](https://github.com/tmpvar/jsdom/issues) (最适合错误报告)
-   IRC 频道 : 自由节日

## 常见问题

### @forbeslindesay/jsdom 是什么？

JavaScript 许多网络标准的执行

### 如何安装 @forbeslindesay/jsdom？

在项目目录运行 npm install @forbeslindesay/jsdom，或使用 pnpm add / yarn add / bun add。

### @forbeslindesay/jsdom 支持 TypeScript 吗？

该包的 package\.json 没有声明类型入口。需要类型提示时，可以在 npm 上查找社区维护的 @types/forbeslindesay\_\_jsdom 是否存在。

### @forbeslindesay/jsdom 支持 ESM 还是 CommonJS？

以 CommonJS 形式发布，可以直接 require\(\)；在 ES Module 项目中也可以用 import 引入（Node\.js 会把 module\.exports 作为默认导出）。

### @forbeslindesay/jsdom 可以商用吗？

@forbeslindesay/jsdom 使用 MIT 许可。宽松许可：允许商业使用、修改和再分发，通常只需在分发时保留原版权与许可声明。以上为概括，不构成法律意见，请以许可原文为准。

### @forbeslindesay/jsdom 的下载量有多少？

根据 npm 官方下载统计，@forbeslindesay/jsdom 在 2026/10/16 – 2026/11/14 这 30 天内被下载 2,018 次，日均约 67 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @forbeslindesay/jsdom 还在维护吗？

最新版本 11\.1\.9 发布于 2017/07/09（9 年前）；至今共发布 10 个版本，其中过去 12 个月发布了 0 个；首次发布于 2017/07/07。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

