1

我正在写一个简单的计数器,我想让这个计数器的安装对用户来说非常简单。我见过的最简单的计数器代码之一(对于安装它的用户)是 Google Analytics Code

所以我想将主要代码存储在一个文件中,安装我的计数器的用户只需要像这样设置 websiteID:

<html><head><title></title></head><body>
<script type="text/javascript" src="http://counterhost.lan/tm.js">
var websiteId = 'XXXXX';
</script>
</body></html>

这是我的代码:

<script type="text/javascript" src="http://counterhost.lan/tm.js">
var page = _gat.init('new');
</script>

这是我的 JS 文件:

(function() {
    var z = '_gat';
    var aa = function init(data) { alert(data); alert(z);};

    function na() {
        return new z.aa();
    }
    na();
})();

我试图理解 Google Analytics javascript 代码,但我没有做到这一点。谁能建议我如何在标签之间指定变量,然后在位于 javascript 文件中的匿名函数中读取它?谢谢。

4

6 回答 6

2

您可以将变量传递给匿名函数,如下所示:

(function(arg1, arg2, arg3) {
    alert(arg1);
    alert(arg2);
    alert(arg3);
})("let's", "go", "redsox");

// will alert "let's", then "go", then "redsox" :)
于 2009-12-16T02:38:44.383 回答
2

在您的示例中,websiteId是一个全局变量。所以它在任何地方都可以访问,包括匿名函数,除非有同名的局部变量

<script> var websiteId = "something"; </script>

稍后在页面或包含的js文件中......

(function() {
    alert(websiteId); //this should work
})();
于 2009-12-16T00:45:09.837 回答
2

谁能建议我如何在标签之间指定变量然后阅读它[...]

如果您的标签同时具有 SRC 属性和 JS 内容,则不会。

<script type="text/javascript" src="http:/x.com/x.js"></script>

..不同于,

<script type="text/javascript">
    var x = 1;
</script>

Dojo 是一种可以选择将 JS 变量添加到 SCRIPT 标记的框架。因此,如果您使用 Dojo,您可以通过编写将变量添加到全局djConfig哈希中,

<script type="text/javascript" src="mxclientsystem/dojo/dojo.js"
    djConfig="
    usePlainJson: true,
    parseOnLoad: true
">
</script>

Dojo 通过运行 SCRIPT 标记并评估自定义djConfig属性来做到这一点。

但是,这并不能解决您的问题。

您确实需要两个 SCRIPT 标签。一种说法,

<script type="text/javascript">
    var websiteId = '123456';
</script>

这将设置一个全局变量websiteId和第二个,

<script type="text/javascript" src="http:/x.com/myreporter.js"></script>

它可以从任何地方加载并读出websiteId变量,我假设它会报告回来。

于 2009-12-16T01:23:56.220 回答
0

我不完全清楚你在问什么,但是...

id您可以使用属性标记任何 HTML 元素,然后用于
document.getEntityById()检索该特定元素。

您还可以为任何 HTML 元素提供具有您自己选择的名称的用户定义属性,然后在 Javascript 中为该元素获取和设置它们。

于 2009-12-16T00:40:45.687 回答
0

我认为您对 JS 对象的调用方式有些困惑。

z是一个字符串,'_gat'. 您不能调用aa()它,因为 String 没有被调用的成员aaaa是存储在局部变量中的独立函数。即使您确实 call aa(),它也不会返回任何内容,因此new在其结果上使用运算符是没有意义的。new只能在构造函数上调用。

我猜你的意思是这样的:

var _gat= function() {

    // Private variable
    //
    var data= null;

    // Object to put in window._gat
    //
    return {

        // Set the private variable 
        //
        init: function(d) {
            data= d;
        }
    };
}();

然后在第二个示例中调用_gat.init('foo')会将变量设置为 website ID 'foo'。这是有效的,因为该对象是在匿名函数内部定义_gat的返回对象,在隐藏变量上保留了一个引用(“闭包”)。{init: function() {...}}data

于 2009-12-16T01:18:46.890 回答
0

如果将src属性指定为元素的一部分,则元素标记本身script内的任何代码script都不会被执行。但是,您可以使用以下代码添加此功能。我从 Crockford(我相信是他)那里得到了这项技术,他在关于渲染性能和为此将脚本异步加载到页面中的无关主题的演讲中使用了它。

JavaScript:

(function() {
    // Using inner class example from bobince's answer
 var _gat = (function() {
     var data= null;

     return {
         init: function(d) {
          console.info("Configuration data: ", d);
             data = d;
         }
     }
 })();

 // Method 1: Extract configuration by ID (SEE FOOT NOTE)
 var config = document.getElementById("my-counter-apps-unique-and-long-to-avoid-collision-id").innerHTML;

 // Method 2: search all script tags for the script with the expected name
 var scripts = document.getElementsByTagName("script");

 for ( var i=0, l=scripts.length; i<l; ++i ) {
  if ( scripts[i].src = "some-script.js" ) {
   config = scripts[i].innerHTML;
   break;
  }
 }

 _gat.init( eval("(" +config+ ")") );
})();

HTML:

<script type="text/javascript" src="some-script.js" id="my-counter-apps-unique-and-long-to-avoid-collision-id">
 {some: "foo", config: "bar", settings: 123}
</script>

这两种方法都有其缺点:

  1. 使用唯一且不冲突的 ID 将使确定正确的脚本元素更加精确和快速;但是,这不是有效的 HTML4/XHTML 标记。在 HTML5 中,你可以定义任意属性,所以当时不会有问题

  2. 此方法是有效的 HTML 标记;但是,如果您的网址可能发生变化(例如:http vs https),我展示的简单比较很容易被破坏,并且可能需要更强大的比较方法

关于eval

两种方法都使用eval. 关于这个特性的典型口头禅是“eval is evil”。然而,这与说在eval 不知道危险的情况下eval使用是邪恶的。

在这种情况下,AFAIK,script标签中包含的数据不会受到注入攻击,因为在将 HTML 解析为 DOM 时,一旦到达该元素,就会执行评估脚本(显示的代码)。之前可能已定义的脚本无法访问计数器script标签中包含的数据,因为在执行它们时该节点不存在于DOM树中。

可能的情况是,setTimeout从先前包含的脚本中执行的定时良好的脚本可能能够在 counter 的script包含和 eval 之间的时间运行;但是,这可能是也可能不是,并且如果可能的话,可能不会如此一致,具体取决于 CPU 负载等。

故事的道德,如果你担心的话,包括一个非eval'ing JSON解析器并使用它来代替。

于 2009-12-16T04:14:58.613 回答