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

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

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

他们是两个问题。

  1. 我应该如何检测代码在哪个浏览器上运行。 例如,这个代码是否可以。 (这段代码是内联的,这意味着它被一些全局代码包围着,可以在两种环境中重用)

     if window? totalPath= "../examples/#{path}" else totalPath= "../../examples/#{path}" 
  2. 我如何在两个环境中使用全局variables? 现在,我正在做下面的事情,但这真的不对。

     if window? window.DocUtils = {} window.docX = [] window.docXData= [] else global.DocUtils= {} global.docX = [] global.docXData = [] 

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

在JavaScript中,variables可以由内部范围重新定义,因此假定环境没有创build名为process的variables,全局或窗口很容易失败,例如,如果使用node.js jsdom模块, API使用示例

 var window = doc.defaultView; 

之后,基于windowvariables的存在检测环境将在该范围内运行的任何模块系统地失败。 使用相同的逻辑,任何基于浏览器的代码都可以轻易地覆盖globalprocess ,因为它们不是该环境中的保留variables。

幸运的是,有一种方法需要全局范围并testing它是什么 – 如果使用new Function()构造函数创build一个新函数,则其执行范围绑定到全局范围,您可以直接将全局范围与预期的价值。 *)

所以要创build一个函数检查全局作用域是否为“窗口”

 var isBrowser=new Function("try {return this===window;}catch(e){ return false;}"); // tests if global scope is binded to window if(isBrowser()) console.log("running under browser"); 

而testing全球范围是否被绑定到“全球”的function将是

 var isNode=new Function("try {return this===global;}catch(e){return false;}"); // tests if global scope is binded to "global" if(isNode()) console.log("running under node.js"); 

try … catch -part将确保如果未定义variables,则返回false

如果你愿意的话, isNode()也可以比较this.process.title==="node"或其他一些在node.js里面find的全局范围variables,但是与全局的比较应该足够了。

http://jsfiddle.net/p6yedbqk/

说明 :build议不要检测运行环境。 但是,它可以在特定的环境中使用,如在全球范围内具有一些已知特性的开发和testing环境。

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

在我看来,这里推荐的策略是使用单例模式来绑定你的设置。 在SO中已经有了一个很好的替代scheme

最简单/最干净的方式来实现JavaScript中的单身人士?

所以,如果你不需要一个“全局”variables,并且你根本不需要环境检测,那么就可以使用单例模式来定义一个模块,它将为你存储这些值。 好吧,可以争辩说,模块本身是一个全局variables,在JavaScript中它实际上是,但至less在理论上它看起来有点干净。

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

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

您可以附加到variables窗口或全局 – 基于情况。 虽然这不是一个推荐的多平台JS应用程序的方式:

 var app = window ? window : global; 

拥有全局variables要好于应用程序的逻辑,但是会由基于不同平台的部分组成。 就像是:

 var app = { env: '', agent: '' }; if (window) { app.env = 'browser'; app.agent = navigator.userAgent; } else if (process) { app.env = 'node'; } 

所以这个想法是你的主应用程序逻辑将是完全相同的,并将使用相同的对象,只有全局对象必须根据环境而改变。 这使得您的应用程序在平台方面更具可移植性和灵活性。

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

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

条件的多级是为了避免由于一些浏览器限制而search未定义的variables时的错误。

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

Interesting Posts