我正在开发一个需要同时在客户端和服务器端工作的 JS 应用程序(在浏览器上的 Javascript 和 Node.js 中),我希望能够重用代码的一部分用于双方。
我发现 window
是一个只能在浏览器上访问的变量,而 global
在节点中,所以我可以检测代码在哪个环境中执行(假设没有脚本声明 window
变量)
他们是两个问题。
- 我应该如何检测代码在哪个浏览器中运行。例如,这段代码是否可以。 (此代码是内联的,这意味着它被一些全局代码包围,可在两种环境中重复使用)
if window?
totalPath= "../examples/#{path}"
else
totalPath= "../../examples/#{path}"
- 如何在两种环境中使用全局变量?现在,我正在执行以下操作,但这确实感觉不对。
if window?
window.DocUtils = {}
window.docX = []
window.docXData= []
else
global.DocUtils= {}
global.docX = []
global.docXData = []
原文由 edi9999 发布,翻译遵循 CC BY-SA 4.0 许可协议
注意:这个问题有两个部分,但因为标题是“环境检测:node.js 或浏览器”——我会先讲这部分,因为我猜很多人来这里是为了寻找答案。一个单独的问题可能是有序的。
在 JavaScript 中,变量可以通过内部作用域重新定义,因此假设环境没有创建名为 process、global 或 window 的变量很容易失败,例如,如果一个人正在使用 node.js jsdom 模块, API 用法示例有
之后,根据
window
变量的存在检测环境,在该范围下运行的任何模块都会系统性地失败。使用相同的逻辑,任何基于浏览器的代码都可以轻松覆盖global
或process
,因为它们不是该环境中的保留变量。幸运的是,有一种方法可以要求全局范围并测试它是什么——如果你使用
new Function()
构造函数创建一个新函数,this
的执行范围被绑定到全局范围您可以将全局范围直接与预期值进行比较。 *)所以要创建一个函数检查全局范围是否为“窗口”将是
测试全局范围是否绑定到“全局”的函数是
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