Javascript 为什么要声明jQuery两次?

Javascript 为什么要声明jQuery两次?,javascript,jquery,Javascript,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.mi

以下代码的目的是什么

请注意,在下面的第二个脚本代码之前,
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>

window.jQuery | | document.write(“”)

当服务器关闭或无法访问时,可以回退到存储在同一服务器上的
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>')
}
//1。尝试下载并运行https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js
// 2. jQuery是否已从CDN成功加载?如果是,将定义为:
if(window.jQuery){
//是的,已经定义好了。很好。不需要更多了。
}
否则{
//不,未定义。请使用我的副本:
文件。写入(“”)
}
您可以找到原始代码


关于
window.jQuery | | document.write(…)
这基本上是上述代码的简写。定义
窗口时,jQuery
将被删除,因此
|
右侧的语句将不会被执行;但是,如果没有定义,它将被定义,并且
|
右侧的语句将被执行。

它将首先尝试使用托管在谷歌CDN上的版本。浏览网站的人可能已经缓存了访问其他网站时的脚本,所以他们最好先尝试一下

如果加载CDN版本,则设置window.jQuery,or短路,代码继续

如果由于某种原因无法加载CDN版本,它会向页面添加另一个脚本标记,指向本地托管的脚本版本


编辑:正如MTCoster在中指出的,这个技巧依赖于JavaScript的正常加载方式。浏览器会暂停执行,直到标记加载或超时。如果jQuery是使用async属性异步加载的,那么这个技巧就不会起作用。

第一个脚本将尝试从外部网站(在本例中为Google CDN)加载jQuery

第二个将尝试在
窗口
中查找jQuery对象,只有在未找到它时,才会从内部链接加载库。这只是CDN失败时的一种退路

window.jQuery || document.write(...)
// the code above means the same as the code below
if (window.jQuery === undefined) document.write(...)
在Javascript中,除了布尔值(true/false),还有truthy和falsy值。与
0
false
未定义
null
不同的任何内容都是真实值

在这种情况下,如果窗口上存在
jQuery
属性,则它将是一个对象,并且将是一个真实值,因此,第二条语句将不会运行(因为第一条语句已经为真-在
操作符中,如果其中任何一条语句为真,它将跳过其他语句(从左到右)


尽管如此,如果
jQuery
属性不存在,这是因为第一个脚本没有正确加载,并且该属性将是
未定义的
,一个错误值。因此,第二个语句将运行,本地jQuery将作为一个回退加载。

如果在某些情况下未达到来自CDN的jQuery,这是一种回退机制像ason一样被防火墙阻止,CDN关闭等

我将再添加一个我去年面临的实际场景。我的一个客户决定在没有internet可用性的情况下在LAN中托管和使用我创建的web应用程序。使用本地IIS,该应用程序已正确部署,但由于CDN不可用而失败,如果我使用上述代码,web应用程序将正常工作第一次没有任何变化


我希望这会有意义:)对我来说这是一个教训。

是的,主要是速度优势。如果已经有jquery,那么加载它会更快。最好的机会是当它在许多网站的同一个地方托管时。所以基本上,你想先尝试一下,然后一劳永逸地得到它。如果失败,获取本地版本。这是一个CDN回退,如下所述:是否有任何保证jquery在完成第二次检查之前会从服务器上完全加载?@user1438893是。当浏览器仍在加载上一个脚本时,它不会开始执行另一个脚本(除非指示它执行其他脚本,而在这里则不是)。如果不是这样的话,就不可能使用任何第三方库,或者事实上,任何依赖于另一个脚本的脚本。很酷的概念,我以前从未见过这种情况。我们是否保证第一个将在第二个开始之前完成下载?@loneboat是的,它将在继续解析页面()之前尝试下载并运行脚本。这就是为什么如果你把脚本标签按一定的顺序放置,它会按这个顺序运行脚本,而不是按下载完成的顺序运行。我[错误地]认为,当它遇到一个外部链接的页面时,它会发出请求并开始下载,然后继续并行解析页面。谢谢@另一方面,HTML5提供了
async
属性,该属性导致
标记的行为与您刚才描述的
window.jQuery | | |…
window.jQuery==未定义的
,如果
window.jQuery
0
,则
版本仍将返回false,如您所述,
false
,或
null