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

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

这是两个问题.

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

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

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

推荐答案

NOTE: This question had two parts, but because the title was "Environment detection: node.js or browser" - I will get to this part first, because I guess many people are coming here to look for an answer to that. A separate question might be in order.

在JavaScript中,变量可以由内部作用域重新定义,因此假设环境没有创建名为process、global或window的变量,则很容易失败,例如,如果使用node.js jsdom模块,API usage example has

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-part将确保如果未定义变量,则返回false.

isNode()还可以比较this.process.title==="node"或在 node 内找到的其他一些全局范围变量.js,如果你愿意的话,但在实践中与全球相比应该足够了.

http://jsfiddle.net/p6yedbqk/

100: detecting the running environment is not recommended. However, it can be useful in a specific environment, like development and testing environment which has some known characteristics for the global scope.

Now - the second part of the answer.环境检测完成后,您可以 Select 要使用哪种基于环境的策略(如果有)将"全局"变量绑定到应用程序.

在我看来,这里推荐的策略是使用单例模式来绑定类内的设置.目前已经有一个很好的备选方案 list

Simplest/cleanest way to implement a singleton in JavaScript

因此,如果您不需要"全局"变量,也不需要环境检测,那么可以使用单例模式定义一个模块,该模块将为您存储值.好吧,我们可以说模块本身是一个全局变量,在JavaScript中它实际上是一个全局变量,但至少在理论上,它看起来更简洁.

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

注意:使用函数构造函数创建的函数不会创建

Node.js相关问答推荐

如何在node.js中以随机顺序调用函数并按顺序操作

为高流量网站优化Node.js实时通知服务

在编译时强制不缩小类型范围

如何获取文件的中间值?

为什么 $or 在带有正则表达式的mongoose 中不能正常工作

Discord.js V14 interaction.editReply 给出了一个无效的 webhook 令牌错误

带权限的机密 Rest-Api - 总是 403 - 我做错了什么?

baseurl64 缓冲区解码

使用 grunt 服务器,如何将所有请求重定向到根 url?

Nodejs-console.error vs util.debug

调用 require 时的 const vs let

容器之间的 Docker HTTP 请求

Passport 登录和持久会话

按日期时间字段获取最新的 MongoDB 记录

gyp WARN EACCES 用户root没有访问开发目录的权限

在 Jade 包含中使用变量

名称类型为 mongoose 的字段

Node.js 连接仅适用于本地主机

如何调试 Gulp 任务?

node.js 中的意外保留字导入