环境检测:node.js或浏览器

新手上路,请多包涵

我正在开发一个需要同时在客户端和服务器端工作的 JS 应用程序(在浏览器上的 Javascript 和 Node.js 中),我希望能够重用代码的一部分用于双方。

我发现 window 是一个只能在浏览器上访问的变量,而 global 在节点中,所以我可以检测代码在哪个环境中执行(假设没有脚本声明 window 变量)

他们是两个问题。

  1. 我应该如何检测代码在哪个浏览器中运行。例如,这段代码是否可以。 (此代码是内联的,这意味着它被一些全局代码包围,可在两种环境中重复使用)
    if window?
       totalPath= "../examples/#{path}"
   else
       totalPath= "../../examples/#{path}"

  1. 如何在两种环境中使用全局变量?现在,我正在执行以下操作,但这确实感觉不对。
    if window?
       window.DocUtils = {}
       window.docX = []
       window.docXData= []
   else
       global.DocUtils= {}
       global.docX = []
       global.docXData = []

原文由 edi9999 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 997
2 个回答

注意:这个问题有两个部分,但因为标题是“环境检测:node.js 或浏览器”——我会先讲这部分,因为我猜很多人来这里是为了寻找答案。一个单独的问题可能是有序的。

在 JavaScript 中,变量可以通过内部作用域重新定义,因此假设环境没有创建名为 process、global 或 window 的变量很容易失败,例如,如果一个人正在使用 node.js jsdom 模块, API 用法示例有

var window = doc.defaultView;

之后,根据 window 变量的存在检测环境,在该范围下运行的任何模块都会系统性地失败。使用相同的逻辑,任何基于浏览器的代码都可以轻松覆盖 globalprocess ,因为它们不是该环境中的保留变量。

幸运的是,有一种方法可以要求全局范围并测试它是什么——如果你使用 new Function() 构造函数创建一个新函数, this 的执行范围被绑定到全局范围您可以将全局范围直接与预期值进行比较。 *)

所以要创建一个函数检查全局范围是否为“窗口”将是

var isBrowser=new Function("try {return this===window;}catch(e){ return false;}");

// tests if global scope is bound to window
if(isBrowser()) console.log("running under browser");

测试全局范围是否绑定到“全局”的函数是

var isNode=new Function("try {return this===global;}catch(e){return false;}");

// tests if global scope is bound to "global"
if(isNode()) console.log("running under node.js");

try…catch 部分将确保如果未定义变量,则返回 false

isNode() 也可以比较 this.process.title==="node" 或在 node.js 中找到的其他一些全局范围变量,但实际上与全局比较就足够了。

http://jsfiddle.net/p6yedbqk/

注意:不推荐检测运行环境。但是,它在特定环境中可能很有用,例如具有某些全球范围已知特征的开发和测试环境。

现在 - 答案的第二部分。 完成环境检测后,您可以选择要使用哪种基于环境的策略(如果有)将“全局”变量绑定到您的应用程序。

在我看来,这里推荐的策略是使用单例模式将您的设置绑定到一个类中。 SO 中已经有一个很好的替代品列表

在 JavaScript 中实现单例的最简单/最干净的方法

所以,如果你不需要“全局”变量,你可能根本不需要环境检测,只需使用单例模式定义一个模块,它会为你存储值。好的,可以说模块本身是一个全局变量,在 JavaScript 中确实如此,但至少在理论上它看起来更简洁一些。

*) https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function

注意:使用 Function 构造函数创建的函数不会为其创建上下文创建闭包;它们总是在全局范围内创建。运行它们时,它们将只能访问自己的局部变量和全局变量,而不能访问调用函数构造函数的范围内的变量。

原文由 Tero Tolonen 发布,翻译遵循 CC BY-SA 4.0 许可协议

由于显然 Node.js 可以同时拥有两者(w/NW.js?),我个人的方法是检测 node 条目是否存在于 process.versions 对象中。

 var isNode = false;
if (typeof process === 'object') {
  if (typeof process.versions === 'object') {
    if (typeof process.versions.node !== 'undefined') {
      isNode = true;
    }
  }
}

多级条件是为了避免由于某些浏览器限制而在搜索未定义变量时出错。

参考: https ://nodejs.org/api/process.html#process_process_versions

原文由 Dan. B. 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题