在jsdom加载的脚本中设置全局变量

时间:2016-01-30 09:02:03

标签: javascript node.js global-variables jsdom

我试图在Node.js中运行一些浏览器代码以简化测试(deasync是原因)。

目前,我使用jsdom来解析唯一的html文件。起初,我试图让它加载脚本,这些脚本链接在<script>标签中。但是由于相对文件路径的一些愚蠢问题,我已经切换到将脚本文件的绝对路径列表作为jsdom.env函数的参数传递。

现在我非常确定jsdom正确地找到了我的脚本,但我不能在其中设置任何全局变量。此外,console.log无法在那里工作。我已经检查过,如果我通过require命令加载脚本,那么全局变量和控制台输出都按预期工作。但是jsdom.env他们没有工作。

我在Windows 7上使用Node.js版本4.2.6。以下4个文件用于重现问题(它们位于同一目录中):

main.js - 以node.exe开头:

var jsdom = require("jsdom");
require("./module");

var window = jsdom.env(
  '<p><a class="the-link" href="https://github.com/tmpvar/jsdom">jsdom!</a></p>',
  [
//  "http://code.jquery.com/jquery.js",
  "file://" + __dirname + "/myjquery.js",
  "file://" + __dirname + "/script.js"
  ],
  undefined,
  function(error, window) {
    console.log("contents of a.the-link:", window.$("a.the-link").text());
    console.log(global.hello, window.hello, global.hi);
  }
);

module.js:

console.log("Hi!");
global.hi = 15

的script.js:

console.log("Hello!");
global.hello = 126;

myjquery.js只是从http://code.jquery.com/jquery.js下载的jQuery。

打印出来:

Hi!
contents of a.the-link: jsdom!
undefined undefined 15

所以它肯定会正确加载myjquery.js,因为它用于打印第一行。此外,它设置一个全局变量并在模块中打印一行,但它不在脚本中执行。

您能解释一下原因并提出解决方法吗?

1 个答案:

答案 0 :(得分:2)

hello全局

global是NodeJS的东西,而不是浏览器的东西。在你的script.js中,如果你想在页面中设置全局变量(比如jQuery那样),你可以在全局范围内声明它们:

var hello = 126;

或将其指定为window上的属性:

window.hello = 126;

或(在全球范围内,如果您没有使用严格模式)到this

this.hello = 126;

如果您执行script.js中的任何一项,{/ 1}}将会在您的回调中设置。

看到window.hello

要在窗口中查看console.log输出的JSDom页面quite clearly says,您必须执行以下操作:

console

看到错误

您提到您没有看到错误(由于// Create and configure a virtual console var virtualConsole = jsdom.createVirtualConsole(); virtualConsole.on("log", function (message) { console.log("console.log called ->", message); }); // Use it in the config object var window = jsdom.env( '<p><a class="the-link" href="https://github.com/tmpvar/jsdom">jsdom!</a></p>', [ // "http://code.jquery.com/jquery.js", "file://" + __dirname + "/myjquery.js", "file://" + __dirname + "/script.js" ], { virtualConsole: virtualConsole }, // <== Here function(error, window) { console.log("contents of a.the-link:", window.$("a.the-link").text()); console.log(window.hello, global.hi); } ); 确实会导致错误,因此会有用;)

JSDom documentation也讨论了如何监听错误:

global.hello = 126;

这只是在我们virtualConsole.on("jsdomError", function (error) { console.error(error.stack, error.detail); }); 设置之后。现在,console等中的错误会报告给Node控制台。

相对路径

你提到了相对路径的一些问题。仅供参考,这对我来说效果很好:

script.js

...直接使用var window = jsdom.env( '<p><a class="the-link" href="https://github.com/tmpvar/jsdom">jsdom!</a></p>', [ "myjquery.js", "script.js" ], { virtualConsole: virtualConsole }, function(error, window) { console.log("contents of a.the-link:", window.$("a.the-link").text()); console.log(window.hello, global.hi); } );

旁注:围绕"http://code.jquery.com/jquery.js"的JSDom文档显示配置对象与上面略有不同。我这样做了:

virtualConsole

而他们的文档显示了这一点:

var window = jsdom.env(
  // ...
  { virtualConsole: virtualConsole },
  // ...
);

区别的原因是您只在代码中使用ES5,因此我进行了翻译。他们正在使用ES2015(ES6)功能,如果属性名称和您从中获取的变量的名称相同,则可以使用简写来指定属性。所以var window = jsdom.env( // ... { virtualConsole }, // ... ); { virtualConsole }在ES2015中完全相同,但前者在ES5及更早版本中不起作用。如果您正在使用当前的Node和JSDom,则可以使用该ES2015功能。