为什么要声明jQuery两次?
以下代码的目的是什么?
请注意,在下面的第二个脚本代码之前, jquery.min.js
已经包含在googleapis
。
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script> <script>window.jQuery || document.write('<script src="/assets/js/vendor/jquery.min.js"><\/script>')</script>
当CDNclosures或无法访问时,它将回jquery.min.js
存储在同一台服务器上的jquery.min.js
文件。
这本质上是说:
// 1. Try to download and run https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js // 2. Was jQuery successfully loaded from the CDN? If so, it will be defined: if (window.jQuery) { // Yes, it's defined. Good. Nothing more needed. } else { // No, it's not defined. Use my copy: document.write('<script src="/assets/js/vendor/jquery.min.js"><\/script>') }
在这里阅读更多 ,你可以在这里find原始代码。
关于window.jQuery || document.write(...)
window.jQuery || document.write(...)
基本上是上面代码的简写。 当定义的window.jQuery
将truthy ,所以在右侧的声明 将不会被执行; 但是,如果它没有被定义,它将是谬误,并在右侧的声明 将被执行。
它试图首先使用托pipe在Google CDN上的版本。 浏览该网站的人有一个机会,已经从访问其他网站caching了确切的脚本,所以他们不妨先尝试一下。
如果加载CDN版本,则设置window.jQuery, 或者短路,代码继续运行。
如果由于某种原因无法加载CDN版本,则会向指向本地托pipe版本的脚本的页面添加另一个脚本标记。
编辑:正如MTCoster在上面的评论中指出的,这个技巧依赖于JavaScript正常加载的方式。 浏览器暂停执行,直到标签加载或超时。 如果jQuery是asynchronous加载使用async属性,这个技巧是行不通的。
第一个脚本将尝试从外部网站(在这种情况下,谷歌CDN)加载jQuery。
第二个将尝试在window
findjQuery对象,只有当它没有find它,然后它会从一个内部链接加载库。 在CDN失败的情况下,这只是一个倒退。
window.jQuery || document.write(...) // the code above means the same as the code below if (window.jQuery === undefined) document.write(...)
在Javascript中,除了布尔(真/假)之外,还有真理和谬误的价值。 任何不同于0
, false
, undefined
和null
都是真值。
在这种情况下,如果jQuery
属性存在于窗口上,它将是一个对象,它将是一个真值,所以,第二个语句将不会运行(因为第一个语句已经是真的 – 在一个OR
运算符中,如果任何陈述是真实的,则跳过其他(从左到右)。
虽然,如果jQuery
属性不存在,那是因为第一个脚本没有正确加载,并且该属性将是undefined
,是一个虚假的值。 所以,第二个语句将运行,并且本地jQuery将作为后备加载。
这是一个回退机制,如果从CDN的jquery由于某种原因,如防火墙阻止,CDN下来等
我会再增加一个我去年面对的实际情况。 我的一个客户决定在没有networking的情况下主持和使用我在局域网中创build的networking应用程序。 在本地IIS中,应用程序正确部署,但由于CDN不可用而失败,如果我使用了上述代码,则Web应用程序将在第一次运行时没有任何变化。
我希望现在有意义:)对我来说,这是一个教训。