我有以下的JavaScript,它将从客户的网站上引用。它使用jQuery 1.5所以我的问题是如果客户端已经加载了jQuery的实例?或者另一种JavaScript库?
我正在使用noConflict()尝试解决这个问题,但它似乎无法正常工作,我无法解决原因。任何帮助表示赞赏
主要问题是我收到一条错误,告诉我jQueryMH未定义,但在我甚至在keepAlive函数上设置间隔之前我已经明确定义了它。
var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.src = '//ajax.googleapis.com/ajax/libs/jquery/1.5.0/jquery.min.js';
script.type = 'text/javascript';
script.onload = script.onreadystatechange = function() {
var jQueryMH = jQuery.noConflict(true);
setInterval(keepAlive(), 5000);
};
head.appendChild(script);
function keepAlive() {
var mhProtocol = ((document.location.protocol == "https:") ? "https://" : "http://");
var randomNumber = Math.floor(Math.random()*10000);
var mhVisitorId = document.cookie.match('mhVisitorId=(.*?)(;|$)');
var urlParamString = "";
if(mhVisitorId) {
urlParamString = "&mhVisitorId=" + encodeURIComponent(mhVisitorId[1]);
}
var mhUrl = "www.urlishere.com";
//var jQueryMH = jQuery.noConflict();
jQueryMH.ajax({
url: mhUrl,
dataType: 'jsonp'
});
}
除此之外,我已经尝试在函数本身中设置noConflict()并且这可以工作并允许我引用jQueryMH,但是我们有以下问题,可能是因为它每次运行函数时都设置noConflict(每个5S)
我设置的测试页面外部包含这个JS脚本已经加载了jQuery 1.8,然后它加载了上面的脚本。因为我的noConflict,我希望jQueryMH.fn.jquery返回1.5.0,jQuery.fn.jquery返回1.8;然而它们都返回1.5.0,这意味着我的noConflict无效,因为jQuery没有保留,因为已经加载到客户网站上的1.8版本库。
答案 0 :(得分:1)
在加载第二个版本之前,您实际上需要noconflict
第一个版本的jQuery,否则第二个版本将覆盖第一个版本。
除此之外,您的未定义变量问题是由于您在函数内调用 我认为你需要先做: 然后像上面那样加载新的jQuery,然后加载 然后恢复原始jQuery: 在全球范围内完成上述所有工作。.noconflict
并将jQuery分配给仅在该函数范围内的范围内的备用变量而引起的。< / p>
var origjQuery = jQuery.noconflict();
noconflict
:var jQueryMH = jQuery.noconflict();
var jQuery = origjQuery.noconflict();
答案 1 :(得分:1)
我构建了一个jQuery的自定义构建,修改了将jQuery分配给全局变量的代码行。
具体来说,我改变了以下代码:
window.jQuery = window.$ = jQuery;
到
window.myCustomJquery = jQuery;
通过这种方式,即使在页面中包含jQuery脚本,我也可以毫无问题地注入我自定义的jQuery构建,而无需密封/冻结实际的全局jQuery或不使用.noConflict(),两种解决方案导致上述问题的原因。
答案 2 :(得分:0)
在任何其他主机上注入脚本时,我确实遇到了这个问题。
正如Alnitak所说,noConflict
如果先加载jQuery,然后覆盖$
变量,而不是相反,则可以正常工作。
我设法构建的解决方法使用ECMAScript 5中的Object.freeze
和Object.seal
方法。
问题是将要覆盖现有网站的变量(例如$
)复制到最终会冻结的对象中。
通过在重写变量之前冻结该对象(在加载jQuery之前),确保原始变量的副本(在您的情况下为$
)将存储在您的对象中,并且它们不能以任何方式被任何方式更改其他剧本。
加载所需的库后,您只需将已冻结的对象属性复制回全局对象,保持主机环境不变。
这是一个使事情更清晰的示例代码:
var aux = {'jQuery' : window.jQuery};
if(Object.freeze)
// prevent anyone from deleting any of the `aux` props
Object.freeze(aux);
if(Object.seal)
// prevent anyone from altering the initial jQuery
// this is necessary because `aux.jQuery` is a copy by reference of the
// window.jQuery, thus any modification in the global jQuery object
// would be reflected in our jQuery copy
Object.seal(aux.jQuery);
var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.src = '//ajax.googleapis.com/ajax/libs/jquery/1.5.0/jquery.min.js';
script.type = 'text/javascript';
script.onload = script.onreadystatechange = function() {
var jQueryMH = jQuery.noConflict(true);
// restore the initial jquery
window.jQuery = aux.jQuery;
alert(jQuery === jQueryMH);
};
当然,您可以扩展功能并将其用于您使用的任何其他库:
var __globalLibs = {},
libsThatYouWantToPreserve = '$ jQuery otherLib'.split(' '),
key;
for(var i=0,l=libsThatYouWantToPreserve.length;i<l;i++)
{
key = libsThatYouWantToPreserve[i];
// copy the contents of the global variable into your object
__globalLibs[key] = window[key];
if(Object.seal)
Object.seal(__globalLibs[key]);
}
if(Object.freeze)
Object.freeze(__globalLibs);
// load jquery and all the other libs
// make copies of your update libs
var jQueryMH = jQuery;
// and then restore the initial variables to the global context
for(var i=0,l=libsThatYouWantToPreserve.length;i<l;i++)
{
key = libsThatYouWantToPreserve[i];
// copy the contents of the global variable into your object
window[key] = __globalLibs[key];
}
// after that, you can just delete your object
delete window.__globalLibs;
唯一的缺点是IE8和更低版本不支持 希望这可以帮助!
P.S。 :您应该将setInterval(keepAlive(), 5000);
更改为setInterval(keepAlive, 5000);
,因为您的构造意味着重复评估keepAlive
返回值(undefined
) - 而不是功能本身 - 每5秒钟。