摘要:我们将用户可控制的控制台称为虚拟控制台,以便将其与和页面内部的区分开来。同样,目前在中是不能够处理相关信息的比如设置这样做会导致虚拟控制台发出,说明此功能未实现,并且没有任何变化也将不会有新的或对象,并且现有对象仍保持当前所有相同的属性值。
jsdom是一个纯粹由 javascript 实现的一系列 web标准,特别是 WHATWG 组织制定的DOM和 HTML 标准,用于在 nodejs 中使用。大体上来说,该项目的目标是模拟足够的Web浏览器子集,以便用于测试和挖掘真实世界的Web应用程序。
最新版本的 jsdom 运行环境需要 node.js v6或者更高的版本。(jsdom v10以下版本在 nodejs v4以下仍然可用,但是我们已经不支持维护了)
v10版本的 jsdom 拥有全新的 API(如下所述).旧的 API 现在仍然支持;详细的参照文档
基本用法const jsdom = require("jsdom"); const { JSDOM } = jsdom;
为了使用 jsdom,主要用到jsdom主模块的一个命名导出的 jsdom 构造函数。往构造器传递一个字符串,将会得到一个 jsdom 构造实例对象,这个对象有很多实用的属性,特别是 window 对象:
const dom = new JSDOM(`Hello world
`); console.log(dom.window.document.querySelector("p").textContent); // "Hello world"
(请注意,jsdom会像浏览器一样解析您传递的HTML,包括隐含的,和标记)
生成的对象是JSDOM类的一个实例,其中包括 window 对象在内的许多有用的属性和方法。一般来说,它可以用来从“外部”对jsdom进行操作,而这些操作对于普通DOM API来说是不可能的。对于不需要任何功能的简单场景,我们推荐使用类似的编码模式
const { window } = new JSDOM(`...`); // or even const { document } = (new JSDOM(`...`)).window;
下面是关于JSDOM类所能做的一切的完整文档,在“JSDOM对象API”部分。
定制 jsdomJSDOM构造函数接受第二个参数,可以用以下方式定制您的jsdom。
简单选项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的解析以及获取子资源时使用的同源限制和referrer。默认值为"about:blank"。
referrer 仅仅影响document.referrer的值。默认没有引用(即为空字符串)。
contentType 影响document.contentType的值,是按照HTML解析文档还是 XML来解析。它的值如果不是text/html或XML mime type 值的话将会抛出异常。默认值为"text/html"。
userAgent 影响navigator.userAgent的值以及请求子资源时发送的User-Agent头。默认值为Mozilla / 5.0($ {process.platform})AppleWebKit / 537.36(KHTML,如Gecko)jsdom / $ {jsdomVersion}。
includeNodeLocations 保留由HTML解析器生成的位置信息,允许您使用nodeLocation()方法(如下所述)检索它。
它还能确保在元素内运行的代码的异常堆栈跟踪中报告的行号是正确的。
默认值为false以提供最佳性能,并且不能与XML内容类型一起使用,因为我们的XML解析器不支持位置信息。
请注意,url 和referrer在使用之前已经被规范化了,例如
如果你传入"https:example.com",jsdom会自动规范化解释为"https://example.com/"。
如果你传递了一个不可解析的URL,该调用将抛出错误。
(URL根据URL标准进行分析和序列化。)
jsdom最强大的功能是它可以在jsdom中执行脚本。这些脚本可以修改页面的内容并访问jsdom实现的所有Web平台API。
但是,这在处理不可信内容时也非常危险。
jsdom沙箱并不是万无一失的,在DOM的内部运行的代码如果足够深入,就可以访问Node.js环境,从而访问您的计算机。
因此,默认情况下,执行嵌入在HTML中的脚本的功能是禁用的:
const dom = new JSDOM(` `); // 脚本默认将不能执行: dom.window.document.body.children.length === 1;
要在页面内启用脚本,可以使用runScripts:"dangerously"选项:
const dom = new JSDOM(` `, { runScripts: "dangerously" }); // 脚本将执行并修改 DOM: dom.window.document.body.children.length === 2;
我们再次强调只有在提供给jsdom的代码是你已知道是安全的代码时方可使用它。如果您运行了任意用户提供的或Internet上的不可信的Node.js代码,可能会危及您的计算机。
假如你想通过来执行外部脚本,你需要确保已经加载了它们。为此,请添加选项resources:"usable" 如下所述。
请注意,除非runScripts设置为"dangerously",否则事件处理程序属性(如 如果您只是试图从“外部”执行脚本,而不是通过元素(和内联事件处理程序)从内部运行“,则可以使用runScripts: "outside-only"选项,该选项会启用window.eval: Hello, world! 由于性能原因,默认情况下会关闭此功能,但可以安全启用。 请注意,我们强烈建议不要试图通过将jsdom和Node全局环境混合在一起(例如,通过执行global.window = dom.window)来“执行脚本”,然后在Node全局环境中执行脚本或测试代码。相反,您应该像对待浏览器一样对待jsdom,并使用window.eval或runScripts: "dangerously"来运行需要访问jsdom环境内的DOM的所有脚本和测试。例如,这可能需要创建一个browserify包作为元素执行 - 就像在浏览器中一样。 最后,对于高级用例,您可以使用dom.runVMScript(脚本)方法,如下所述。 jsdom没有渲染可视内容的能力,并且默认情况下会像无头浏览器一样工作。它通过API(如document.hidden)向网页提供提示,表明其内容不可见。 当pretendToBeVisual选项设置为true时,jsdom会假装它正在呈现并显示内容。它是这样做的: 更改document.hidden以返回false而不是true 更改document.visibilityState以返回“visible”而不是“prerender” 启用window.requestAnimationFrame() 和window.cancelAnimationFrame()方法,否则不存在 请注意,jsdom仍然不做任何布局或渲染,因此这实际上只是假装为可视化,而不是实现真正的可视化Web浏览器将实现的部分。 默认情况下,jsdom不会加载任何子资源,如脚本,样式表,图像或iframe。如果您希望jsdom加载这些资源,则可以传递resources: "usable"选项,该选项将加载所有可用资源。资源列表如下: frame 和 iframe,通过 和 实现 样式,通过
脚本,通过,但是前提是runScripts: "dangerously"设置了 图片,通过,但是前提是canvas(或者 canvas-prebuilt) npm 包已安装 未来,我们计划通过此选项提供更多的资源加载定制,但现在只提供的两种模式:"default"和 "usable"。 像网页浏览器一样,jsdom也具有“控制台”的概念。通过在文档内执行的脚本以及来自jsdom本身实现的信息和记录会从页面直接发送过来。我们将用户可控制的控制台称为“虚拟控制台”,以便将其与Node.js console API和页面内部的window.console API区分开来。 默认情况下,JSDOM构造函数将返回一个具有虚拟控制台的实例,该虚拟控制台将其所有输出转发到Node.js控制台。为了创建自己的虚拟控制台并将其传递给jsdom,可以通过执行下面代码来覆盖此默认值 这样的代码将创建一个没有任何行为的虚拟控制台。您可以为所有可能的控制台方法添加事件侦听器来为其提供行为: (请注意,最好在调用 new JSDOM()之前设置这些事件侦听器,因为在解析期间可能会发生错误或控制台调用脚本错误。) 如果你只是想将虚拟控制台输出重定向到另一个控制台,比如默认的Node.js,你可以这样做 还有一个特殊的事件,"jsdomError",它的触发将通过错误对象来记录jsdom本身的错误。这与错误消息在Web浏览器控制台中的显示方式类似,即使它们不是由console.error输出的。到目前为止,错误会按照下面的方式输出: 加载或解析子资源时出错(脚本,样式表,frames和iframe) 不是由window onerror事件处理程序处理的脚本执行错误,它将会返回true或调用event.preventDefault() 由于调用jsdom没有实现的方法而导致的错误,例如window.alert,兼容性的 web 浏览器都实现了这些方法 如果您使用sendTo(c)将错误发送给c,则默认情况下,它将使用来自"jsdomError"事件的信息调用console.error。如果您希望保持事件与方法调用的严格的一对一映射,并且可能自己处理"jsdomError",那么您可以执行 像网页浏览器一样,jsdom也具有cookie jar的概念,存储HTTP cookie 。在文档的同一个域上一个URL,并且没有标记为HTTP only的cookies,可以通过document.cookie API来访问。此外,Cookie jar中的所有cookie都会影响子资源的http加载。 默认情况下,JSDOM构造函数将返回一个带有空cookie的实例。要创建自己的cookie jar并将其传递给jsdom,可以通过以下代码来覆盖默认值 如果您想要在多个jsdoms中共享同一个cookie jar,或者提前使用特定的值来填充cookie jar,这将非常有用。 Cookie jar包由tough-cookie包提供的。jsdom.CookieJar构造函数是tough-cookie cookie jar的子类,并且默认设置了looseMode:true选项,因为它更符合浏览器的行为方式。如果您想自己使用tough-cookie的方法和类,则可以使用jsdom.toughCookie模块导出来访问使用jsdom打包的tough-cookie模块实例。 jsdom允许您在很早的时候介入创建jsdom:创建Window和Document对象之后,但在解析任何HTML并使用节点填充文档之前: Hello 如果您希望以某种方式修改环境,这尤其有用,例如添加jsdom不支持的Web API的填充程序。 一旦你构建了一个JSDOM对象,它将具有以下有用的功能: window属性: window对象的key 从Window 对象检索而来 nodeLocation()方法将查找DOM节点在源文档中的位置,并返回节点的parse5位置信息: Hello
请注意,只有您设置了includeNodeLocations选项才能使用此功能;由于性能原因,节点位置默认为关闭。 Node.js的内置vm模块允许您创建Script实例,这些脚本实例可以提前编译,然后在给定的“VM上下文”上运行多次。在这个场景背后,jsdom Window是一个确定的VM上下文。要访问此功能,请使用runVMScript()方法: 这是高级功能,除非您有特殊的需求,否则我们建议坚持使用普通的DOM API(如window.eval()或document.createElement(“script”))。 window.top属性在规范中被标记为Unforgeable,这意味着它是一个不可配置的私有属性,因此在jsdom内运行的普通代码是不能覆盖或遮挡它的,即使使用Object.defineProperty。 同样,目前在jsdom中是不能够处理navigation相关信息的(比如设置window.location.href ="https://example.com/");这样做会导致虚拟控制台发出"jsdomError",说明此功能未实现,并且没有任何变化,也将不会有新的Window或Document对象,并且现有window.location对象仍保持当前所有相同的属性值。 但是,如果您从 jsdom 窗口之外进行演示,例如在一些创建jsdoms的测试框架中,可以使用特殊的reconfigure()方法覆盖其中的一个或两个: 请注意,更改jsdom的URL将影响所有返回当前 document URL的API,例如window.location,document.URL`和document.documentURI,以及文档中相对URL的解析以及同源检查和提取子资源时使用的引用。但是,它不会执行导航到该URL的内容;DOM的内容将保持不变,并且不会创建Window,Document`等新的实例。 除了JSDOM构造函数本身之外,jsdom还提供了一个返回 Promise 的工厂方法,用于通过URL构建一个jsdom实例 如果URL有效且请求成功,则onFullfilled回调执行并返回JSDOM实例。任何URL重定向都将遵循其最终目的地。 fromURL()提供的参数选项与提供给JSDOM构造函数的选项类似,但具有以下额外的限制和后果:
url 和 contentType 参数不能被提供
referrer 选项用作初始请求的HTTP Referer请求头
userAgent 选项用作任何请求的HTTP User-Agent请求头 生成的jsdom的url 和 contentType和referrer是 由 http response来决定 任何通过HTTP Set-Cookie响应头设置的cookie都存储在jsdom的cookie jar中。同样,已提供的cookie jar中的任何cookie都会作为HTTP Cookie请求标头发送。 初始的请求并不能无限定制到像request npm 包一样的程度;fromURL()旨在为大多数情况提供便利的API。如果您需要更好地控制初始请求,您应该自己执行它,然后手动使用JSDOM构造函数。 与fromURL()类似,jsdom还提供了一个fromFile()工厂方法,用于从文件名构建jsdom 如果可以打开给定的文件,则onFullfilled回调执行并返回JSDOM实例。和Node.js API一样,文件名是相对于当前工作目录的。 fromFile()提供的选项与提供给JSDOM构造函数的选项相似,但具有以下额外的默认值:
url选项将默认为给定文件名相对应的文件URL,而不是"about:blank"
假如给定的文件名是以.xhtml或者.xml为后缀的话,contentType选项默认为"application/xhtml+xml";反之为"text/html"。 对于最简单的情况,你可能不需要一个完整的JSDOM实例及其所有相关的功能。您甚至可能不需要Window或Document!相反,你只需要解析一些HTML片段,并获得一个你可以操作的DOM对象。为此,我们提供了fragment(),它可以从给定的字符串中创建一个DocumentFragment: Hello Hi!`);
frag.childNodes.length === 2;
frag.querySelector("strong").textContent = "Why hello there!";
// etc. frag是DocumentFragment的实例对象,其内容是通过提供的字符串解析创建的。解析是通过使用元素完成的,因此您可以在其中包含任何元素(包括具有奇怪解析规则的元素,如 fragment()工厂函数的所有调用结果的DocumentFragments实例都会共享相同的Document和Window。这允许多次调用fragment()而没有额外的开销。但这也意味着对fragment()的调用不能用任何选项自定义。 请注意,对DocumentFragments的序列化并不像使用JSDOM对象那样容易。如果你需要序列化你的DOM,你应该直接使用JSDOM构造函数。但对于包含单个元素的片段的特殊情况,通过常规方法就很容易做到。 Hello Hello jsdom支持使用canvas或canvas-prebuilt包来扩展任何使用canvas API的元素。为了做到这一点,您需要将canvas作为依赖项加入到您的项目中,和 jsdom包并列。如果jsdom可以找到canvas包,它将使用它,但是如果它不存在,那么元素的行为就像 除了提供一个字符串外,JSDOM构造函数还支持Node.js Buffer或标准JavaScript二进制数据类型(如ArrayBuffer,Uint8Array,DataView等)的形式提供二进制数据。当完成后,jsdom将从提供的字节进行嗅探编码,就像浏览器扫描标签一样。 这种编码嗅探也适用于JSDOM.fromFile()和JSDOM.fromURL()。在后一种情况下,就像在浏览器中一样,任何与response响应一起发送的Content-Type头信息优先级更高。 请注意,在许多情况下,提供字节这种方式可能比提供字符串更好。例如,如果您试图使用Node.js的buffer.toString("utf-8")API,则Node.js将不会去除任何前导BOM。如果您将此字符串提供给jsdom,它会逐字解释,从而使BOM保持不变。但jsdom的二进制数据解码代码将剥离前导的BOM,就像浏览器一样;在这种情况下,直接提供buffer将会得到想要的结果。 jsdom中定义的定时器(通过window.setTimeout或window.setInterval设置)将在window上下文中执行代码。由于进程在不活跃的情况下无法执行未来的定时器代码,所以卓越的jsdom定时器将保持您的Node.js进程处于活动状态。同样,对象不活跃的情况下也没有办法在对象的上下文中执行代码,卓越的jsdom定时器将阻止垃圾回收调度它们的window。 如果你想确保关闭jsdom窗口,使用window.close(),它将终止所有正在运行的定时器(并且还会删除 window和document上的任何事件监听器)。 使用browserify模块,jsdom某些方面也支持在Web浏览器中运行。也就是说,在Web浏览器中,您可以使用被browserify模块编译过的jsdom去创建完全独立的普通JavaScript对象集,其外观和行为与浏览器的现有DOM对象非常相似,但完全独立于它们,也就是"虚拟DOM"! jsdom的主要目标对象仍然是Node.js,因此我们使用仅存在于最新Node.js版本(即Node.js v6 +)中的语言特性功能。因此,在旧版浏览器可能无法正常工作。(即使编译也不会有多大帮助:我们计划在jsdom v10.x的整个过程中广泛使用Proxy。) 值得注意的是,jsdom在web worker中能很好的运行。项目的开发者@lawnsea使这一功能点成为可能,他发表了一篇关于他的项目的论文,该论文就使用了这种能力。 在Web浏览器中运行jsdom时,并非所有的工作都完美。有些情况下,这是由于基础的条件限制(比如没有文件系统访问),但有些情况下也是因为我们没有花足够的时间去进行适当的小调整。欢迎大家来提BUG。 从Node.js v6开始,您可以使用Chrome Devtools来调试程序。请参阅官方文档了解如何使用。 默认情况下,jsdom元素在控制台中被格式化为普通的旧JS对象。为了便于调试,可以使用jsdom-devtools-formatter,它可以让你像真正的DOM元素一样调试它们。 使用jsdom时,开发者在加载异步脚本时经常遇到麻烦。许多页面异步加载脚本,但无法分辨脚本什么时候完成,因此无法知道何时是运行代码并检查生成的DOM结构的好时机。这是一个基本的限制;我们无法预测网页上的哪些脚本会做什么,因此无法告诉您脚本何时加载完毕。 这个问题可以通过几种方法来解决。如果您能控制页面逻辑,最好的方法是使用脚本加载器提供的机制来检测何时加载完成。例如,如果您使用像RequireJS这样的模块加载器,代码可能如下所示: 如果您不能控制该页面,则可以尝试其他解决方法,例如轮询检查特定元素是否存在。有关更多详细信息,请查看#640中的讨论,尤其是@ matthewkastor的深刻见解。 目前,对于大多数Web平台API,jsdom在多个看似独立的jsdoms之间共享相同的类定义。这将意味着,可能会出现以下情况 这主要是出于性能和内存的原因:如果在Web平台上每次创建jsdom时,创建所有类的多带带副本,开销将会相当昂贵。 尽管如此,我们仍然有兴趣在有一天提供一个选项配置来创建一个“独立”的jsdom,但要牺牲一些性能。 与v9.x之前的旧版jsdom API相比,新API显然缺少对资源加载的精细控制。先前版本的jsdom允许您设置request时使用的选项(既可以用于初始请求,也可以用于旧版本的JSDOM.fromURL()和子资源请求)。他们还允许您控制请求哪些子资源并将其应用于主文档,以便您可以下载样式表,但不下载脚本文件。最后,他们提供了一个可定制的资源加载器,可以拦截任何传出的请求并用完全合成的response 响应来结束。 以上这些功能尚未在新的jsdom API中实现,尽管我们也希望尽快将它们添加回来,但不幸的是,这需要相当大的幕后工作去实施。 同时,请随时使用旧的jsdom API来访问此功能。它一直处于支持和维护中,但它不会获得新功能。旧的文档位于lib/old-api.md中。 目前jsdom中有很多缺失的API,尽管我们也想要在jsdom中添加新的功能并保持最新的Web规范。请随时为缺失的任何内容提交issue,但我们是一个很小并且忙碌的团队,因此大家一起来提交 pull request可能会更好。 除了我们尚未拥有的功能之外,还有两个主要功能目前超出了jsdom的范围。这些是: Navigation:在点击链接或赋值location.href或类似操作时可以更改全局对象和所有其他的对象。 Layout:计算CSS元素的视觉布局的能力,这会影响诸如getBoundingClientRects()或者诸如offsetTop之类的属性 目前,jsdom对某些功能的某些方面具有虚拟行为,例如操作navigation 时向虚拟控制台发送“未实现的”"jsdomError",或者为许多与布局相关的属性返回0。您通常可以在代码中解决这些限制,例如通过在爬网过程中为每个页面创建新的JSDOM实例,或使用Object.defineProperty更改各种与布局相关的getter和方法的返回值 请注意,相同领域中的其他工具(如PhantomJS)确实支持这些功能。在wiki上,我们有关于jsdom vs. PhantomJS的更完整的比较介绍。 如果您需要jsdom的帮助,请随时使用以下任何方式:
邮件组(问题最好以"how do i"的形式)
报iusse(最好用BUG 报告) IRC频道:#jsdom on freenode 以上文档翻译自开源项目 jsdom,如有翻译错误,欢迎指正。 jsdom 原文链接 jsdom 项目链接 jsdom 中文翻译wiki链接 原文博客地址 文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。 转载请注明本文地址:https://www.ucloud.cn/yun/94976.html 摘要:酷库,每天两分钟,了解一个流行库。昨天认识了一个在环境下操作的库,实现了接口,用起来十分方便。今天,我们要学习的就是一个纯实现的,可以在环境中模拟出环境,像这样对依赖的库就可以在中运行了。
NPM酷库,每天两分钟,了解一个流行NPM库。
昨天认识了一个在Node.js环境下操作HTML的库 cheerio,cheerio实现了jQuery接口,用起来十分方便。为什么不直接用jQuery... 摘要:酷库,每天两分钟,了解一个流行库。昨天认识了一个在环境下操作的库,实现了接口,用起来十分方便。今天,我们要学习的就是一个纯实现的,可以在环境中模拟出环境,像这样对依赖的库就可以在中运行了。
NPM酷库,每天两分钟,了解一个流行NPM库。
昨天认识了一个在Node.js环境下操作HTML的库 cheerio,cheerio实现了jQuery接口,用起来十分方便。为什么不直接用jQuery... 摘要:但是,如果我们使用过多的函数式编程的抽象概念,我们的函数式编程也会非常难以理解。相比于不太合理的纯函数式编程,我们的代码更加可读理解和修改,这也是我们重构代码的目的。
本文是篇译文,原文链接An Introduction to Reasonably Pure Functional Programming,不当之处还请指正。
一个好的程序员应该有能力掌控你写的代码,能够以最简单的方法使你... 摘要:前同事留下的测试,是基于浏览器的,主要还是功能测试。这里不详细说怎么在浏览器端使用测试了。而且作者也是建议和支持这样做的,简单明了的测试脚本,重要性有时候可能和测试本身一样重要。经测试,在浏览器也有这种问题。
2016-09-03 更新
随着在工作学习中更多地接触、使用测试工具,发现自己在本文中的一些记录是不准确、不正确的。
今天(九月三日)在家看了 NingJs 的直播,其中有一个分... 阅读 3486·2019-08-30 12:58 阅读 882·2019-08-29 16:37 阅读 2763·2019-08-29 16:29 阅读 3089·2019-08-26 12:18 阅读 2345·2019-08-26 11:59 阅读 3371·2019-08-23 18:27 阅读 2722·2019-08-23 16:43 阅读 3263·2019-08-23 15:23const window = (new JSDOM(``, { runScripts: "outside-only" })).window;
window.eval(`document.body.innerHTML = "
const window = (new JSDOM(``, { pretendToBeVisual: true })).window;
window.requestAnimationFrame(timestamp => {
console.log(timestamp > 0);
});
const virtualConsole = new jsdom.VirtualConsole();
const dom = new JSDOM(``, { virtualConsole });
virtualConsole.on("error", () => { ... });
virtualConsole.on("warn", () => { ... });
virtualConsole.on("info", () => { ... });
virtualConsole.on("dir", () => { ... });
// ... etc. See https://console.spec.whatwg.org/#logging
virtualConsole.sendTo(console);
virtualConsole.sendTo(c, { omitJSDOMErrors: true });
Cookie jars(存储Cookie的容器)
const cookieJar = new jsdom.CookieJar(store, options);
const dom = new JSDOM(``, { cookieJar });
const dom = new JSDOM(`
virtualConsole和cookieJar:可以传入或者使用默认值const dom = new JSDOM(`hello`);
dom.serialize() === "hello";
// Contrast with:
dom.window.document.documentElement.outerHTML === "hello";
通过nodeLocation(node)获取 dom 节点的源位置信息
const dom = new JSDOM(
`
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;
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.fromURL("https://example.com/", options).then(dom => {
console.log(dom.serialize());
});
JSDOM.fromFile("stuff.html", options).then(dom => {
console.log(dom.serialize());
});
const frag = JSDOM.fragment(`
)。
const frag = JSDOM.fragment(`
其他值得注意的功能
支持 Canvas
// On the Node.js side:
const window = (new JSDOM(...)).window;
window.onModulesLoaded = () => {
console.log("ready to roll!");
};
const dom1 = new JSDOM();
const dom2 = new JSDOM();
dom1.window.Element.prototype.expando = "blah";
console.log(dom2.window.document.createElement("frameset").expando); // logs "blah"
相关文章
NPM酷库:jsdom,纯JS实现的DOM
NPM酷库:jsdom,纯JS实现的DOM
合理的使用纯函数式编程
使用 ava 和 jsdom 做前端测试
发表评论
0条评论
SHERlocked93
男|高级讲师
TA的文章
阅读更多
angularjs特效之分散的字符串--解析compile link $compile $inter
overflow:hidden失效问题
如何对GitHubPages上的静态资源进行CDN加速
React生命周期
一个前端菜鸟的成长历程
Smartour——让网页导览变得更简单
apply与call方法
NEO DAPP全球区块链应用开发挑战赛