如何封装第三方JavaScript文件,使其不受';不要污染全球范围?
我的一个客户询问他们是否可以添加一些JavaScript来跟踪他们网站上的用户行为。乍一看,我担心它会干扰网站上的其他第三方分析脚本,因为看起来双方都使用了相同的JavaScript压缩器。我不想梳理和搜索每一个可能的命名冲突,所以 是否有一种方法可以包含第三方脚本(位于单独域上的脚本文件),但将它们包装在自己的命名空间中,或赋予它们自己的作用域,这样它们就不会与其他全局声明的变量和函数冲突?如下所示:如何封装第三方JavaScript文件,使其不受';不要污染全球范围?,javascript,Javascript,我的一个客户询问他们是否可以添加一些JavaScript来跟踪他们网站上的用户行为。乍一看,我担心它会干扰网站上的其他第三方分析脚本,因为看起来双方都使用了相同的JavaScript压缩器。我不想梳理和搜索每一个可能的命名冲突,所以 是否有一种方法可以包含第三方脚本(位于单独域上的脚本文件),但将它们包装在自己的命名空间中,或赋予它们自己的作用域,这样它们就不会与其他全局声明的变量和函数冲突?如下所示: (function() { // insert code here })(); 享
(function() {
// insert code here
})();
享受;) 这应该不是问题。Javascript压缩器不会重命名全局变量(出于明显的原因),任何设计良好的脚本都不会公开许多(任何)全局变量。如果他们希望您在页面上部署它,他们有责任防止冲突。按隔离顺序:
<div>...Your content...</div>
<iframe src="tracker.html"
width="10" height="10"
style="position:absolute; top:-100px"></iframe>
…您的内容。。。
tracker.html(可选整个内容)
这是基本的结构,但需要更多的设置,否则所有的流量似乎都来自tracker.html。对于跟踪脚本,我建议在iframe的查询字符串中提供顶部(真实)页面的路径:“tracker.html?u=thispage.html”。您可以在服务器端或通过javascript设置查询字符串:
page.html(再次)
…您的内容。。。
(功能(){
var iframe=document.createElement('iframe');
iframe.src='tracker.html?u='+escape(location.href);
iframe.width=iframe.height=1;
iframe.style.position='绝对';
iframe.style.top='-100px';
var nodes=document.getElementsByTagName('script');
var s=节点[nodes.length-1];
s、 parentNode.insertBefore(iframe,s);
})();
如果路径足以进行跟踪,您可以选择使用location.pathname而不是location.href(具有协议、域等)
毕竟。。。如果跟踪脚本来自一个有信誉的来源(,等等),我建议相信他们不要介入你的页面变量和函数。选项1和2实际上适用于信任度较低的情况。具体取决于您想要做什么 1)您希望在页面中加载第三方脚本,以确保它不会破坏您的脚本。 你在这里做不了什么。
请第三方执行干净的脚本。。。。通常不太可能
在iframe中加载脚本。。。。可能会使脚本变得无用 也许有办法,但可能很愚蠢:
通过ajax加载脚本(可能需要一个代理以避免跨域),使用脚本内容创建一个JS函数(
new function(“脚本内容”);
),然后执行该函数(您也可以使用eval…这是一样的)。
通过这种方式,您可以管理提供给函数的参数,例如,通过这种方式可以保护全局变量。
这样做可能是打破第三方脚本的好方法。它会保护你吗?。。。也许吧
无论如何,您还应该保护自己不受第三方脚本的影响。无论何时尝试使用在第三方脚本中声明的变量,请始终检查变量是否已定义,以确保已加载脚本
2)您希望以一种不会被任何第三方脚本破坏的方式编写脚本
第一:全局变量是危险的。
你不知道是谁做的,你不知道是谁修改的。。。不要相信他们
您可以信任一个变量:全局范围内的this关键字。它应该是窗口对象,并且这个对象应该受到一些保护(至少应该是一个常量)
如果必须创建数组、字符串、regExp。。。尽量不要用“新事物()
”的方式来做
var myArray = []; // not new Array();
var myRegExp = /^myRegExp$/; // not new RegExp('^myRegExp$');
var myString = 'myString'; // not new String('myString');
例如,可以覆盖数组变量。如果你使用[],你不会介意的
当然,在有些情况下,你不能用另一种方式,但尽量不要这样做
由于您不能信任全局变量,因此还应该避免创建一些全局变量。只创建绝对必要的全局变量。其他一切都应该是本地的。如果您的脚本较少受到干扰,其他人可能也会尝试这样做
要做到这一点(主要使用局部变量),您应该在“保护区”中工作。实现这一点的一个好方法是使用匿名自执行函数
(function () {
// Your code here
}());
您还可以将全局变量传递给此“基函数”。这有利于缩小和保护。您还可以获取一个“未定义”变量作为参考,以检查变量是否已定义
(function (window, alert, Array, undef) {
// Your code here
alert('I\'m safe here.');
if([] instanceof Array) {
alert('I\'ve got the real Array object');
}
if(window.jQuery === undef) {
alert('jQuery not loaded');
}
}(this, this.alert, this.Array));
我认为这样你的脚本应该得到一点保护。可能还有其他事情我忘记了,但这是一个好的开始。请注意,如果您的客户端不使用var do declare变量,它们将最终位于全局范围内。或者,如果第三方手动将它们添加到全局命名空间(window.*=123;)中,我的意思是他们希望我在我的每个页面布局中添加一个
标记。啊,在这种情况下,除非你善意地询问第三方,否则你可能无法影响它。第三方脚本无论如何都不应该污染全局范围,但不是每个人都是ri
(function () {
// Your code here
}());
(function (window, alert, Array, undef) {
// Your code here
alert('I\'m safe here.');
if([] instanceof Array) {
alert('I\'ve got the real Array object');
}
if(window.jQuery === undef) {
alert('jQuery not loaded');
}
}(this, this.alert, this.Array));