如何封装第三方JavaScript文件,使其不受';不要污染全球范围?

如何封装第三方JavaScript文件,使其不受';不要污染全球范围?,javascript,Javascript,我的一个客户询问他们是否可以添加一些JavaScript来跟踪他们网站上的用户行为。乍一看,我担心它会干扰网站上的其他第三方分析脚本,因为看起来双方都使用了相同的JavaScript压缩器。我不想梳理和搜索每一个可能的命名冲突,所以 是否有一种方法可以包含第三方脚本(位于单独域上的脚本文件),但将它们包装在自己的命名空间中,或赋予它们自己的作用域,这样它们就不会与其他全局声明的变量和函数冲突?如下所示: (function() { // insert code here })(); 享

我的一个客户询问他们是否可以添加一些JavaScript来跟踪他们网站上的用户行为。乍一看,我担心它会干扰网站上的其他第三方分析脚本,因为看起来双方都使用了相同的JavaScript压缩器。我不想梳理和搜索每一个可能的命名冲突,所以

是否有一种方法可以包含第三方脚本(位于单独域上的脚本文件),但将它们包装在自己的命名空间中,或赋予它们自己的作用域,这样它们就不会与其他全局声明的变量和函数冲突?

如下所示:

(function() {
    // insert code here
})();

享受;)

这应该不是问题。Javascript压缩器不会重命名全局变量(出于明显的原因),任何设计良好的脚本都不会公开许多(任何)全局变量。如果他们希望您在页面上部署它,他们有责任防止冲突。

按隔离顺序:

  • 托管在不同域上的(i)帧-不可能直接交互
  • 托管在同一域上的(i)帧-仅通过显式窗口/帧引用进行交互
  • 一个自动执行的匿名函数-交互很简单,但是行为良好的代码可以被隔离
  • 无-希望没有人使用相同的变量或函数名
  • 这取决于第三方脚本,但我通常倾向于#2。交互是可能的,但您可以避免随意使用document.write和全局命名空间污染

    编辑:#2的示例

    在page.html中

    <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));