if (typeof window !== 'undefined')的目的是什么?

51

打电话的目的是什么

if (typeof window !== 'undefined') 

我在JSPM插件CSS以及其他一些库中看到了它。


对于那段代码的作者和使用者而言,它在询问:“我是在Chrome还是Node.js中运行?”……这个巧妙的混合代码可以在JavaScript运行的“两个”地方工作。 </sarcasm> - dandavis
2个回答

56

这是一个惯用的检查方法,用于确定脚本是否在网页内运行在浏览器中。

人们可能会认为JavaScript只能在网页中运行,因为它最初就是为此而设计的,但这并不正确:JavaScript是一种多才多艺的语言,也可以用于编写Node.js或IIS的Active Server Pages(自1996年以来!)中的服务器端代码,或者在"Web Workers"中使用,这些是在后台运行的网页脚本。

在网页中,有几个固有对象,例如window,其他环境(如Node.js)将没有window,但可能有其他对象,如console(现在大多数浏览器都存在console,但最初并不存在)。

例如,在不同的上下文中,脚本的全局范围内可用的对象是不同的(此列表不是详尽无遗的):

在所有 JavaScript 上下文中,都可以使用一组标准对象,例如:
  • MathDate
  • ObjectNumberFunctionString 等(表示内置类型的对象)等
在网页的脚本(在 <script> 标签内)中:
  • Window(接口)作为全局对象 window 公开,也是实际的全局作用域对象(因此在全局作用域中声明 var foo 实际上创建了属性 window.foo!)
  • 因此,document 全局对象实际上是访问 window.document 属性。
在 Node.js 服务端脚本 中:
  • 由于 Node.js 不是带有 DOM 的 Web 浏览器,因此没有像 window 全局对象或 documentnavigator 之类的属性,而是通过全局对象公开其 API,例如:
    • console
    • process
    • exports
在网页的 Web Worker 脚本 中:
  • 在 Web Worker 中也没有 window 对象,因此全局作用域是一个 WindowOrWorkerGlobalScope 对象,该对象通过属性公开由浏览器提供的对象,例如:
    • caches
    • indexedDB
    • origin
在使用 JScript 的 IIS Active Server Pages 中:
  • response(用于向响应流写入内容)
  • request(用于从传入的 HTTP 请求中读取内容)
  • ApplicationSession(用于在请求之间保留数据)
在 Microsoft Windows 的 Shell Script Host 中:
  • WScript 全局对象公开了脚本主机的功能。

2
@Blindy window对象的类型,由typeof运算符返回的结果将等于字符串“undefined”。 - Maximillian Laumeister
我来晚了,但是 if (window !== undefined) 能达到同样的效果吗?typeof 和字符串相等性检查是否必要? - SheffDoinWork
1
@sheffDoinWork 这是不安全的,因为只有最近JS引擎才使undefined不可变。typeof始终是安全的。 - Dai
2
@SheffDoinWork 在某些情况下,直接引用窗口实际上会导致“窗口未定义”错误。无论如何,在Windows脚本宿主中都是这样。 - trlkly
1
@SheffDoinWork 在JS中,字面量字符串相等检查与整数相等检查一样快,因为JS字符串是不可变的,并且在解释器(或JIT)运行之前,解析器会将字面量存储在内部:因此只需进行简单的指针比较。在JS中使用字面量字符串不要感到难过。 - Dai
显示剩余5条评论

25

这可以用来检测代码是否在典型的浏览器环境中运行(例如,具有浏览器 DOM 的环境)还是在其他 JS 环境中运行,因为window对象存在于典型的浏览器 JS 中,但在像 node.js 或甚至是浏览器中的 webWorker 中不存在。

如果window对象不存在,则

typeof window === 'undefined'

所以你问的代码是:

if (typeof window !== 'undefined') 

如果window对象作为顶级变量存在,将执行if块。

在您链接的特定代码中,这是为了防止在非浏览器环境中使用插件时执行引用DOM对象(如document)的针对浏览器的代码。


@dandavis - 你提到Workers()的评论是从哪来的? 我并没有说过Workers() - jfriend00
@dandavis - 我不明白webWorker代码与这个问题有什么关系。抱歉,我只是不理解你的评论。这段代码检测类似于浏览器的“window”对象是否存在。这本身可以告诉您DOM及其相关对象是否可能存在(与node.js不同),但它不能告诉您有关环境的所有信息。环境中的其他一些事物可能需要其他测试(这不是问题的主题)。在引用的特定代码中,它用于决定是否可以使用DOM。 - jfriend00
一个小细节是,并非所有浏览器JS都有_window_顶级对象,例如Workers,但通常你是正确的 ;) - dandavis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接