什么是“var _gaq = _gaq || [];”?

IT技术 javascript google-analytics
2021-03-07 23:15:56

Google Analytics 中的异步跟踪代码如下所示:

var _gaq = _gaq || []; 
_gaq.push(['_setAccount', 'UA-XXXXX-X']); 
_gaq.push(['_trackPageview']); 

(function() { 
  var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; 
  ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; 
  var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); 
})(); 

关于第一行:

var _gaq = _gaq || []; 

我认为它确保如果_gaq已经定义,我们应该使用它,否则我们应该使用数组。

谁能解释一下这是干什么用的?

另外,_gaq重命名有关系吗?换句话说,Google Analytics 是否依赖于名为 的全局对象_gaq

6个回答

这一行是为了在同一页面中允许多个 GA 代码段。它确保第二个片段不会覆盖第一个定义的 _gaq。

GA 异步跟踪首先将 _gaq 定义为一个数组。这个数组就像一个队列,它允许您将配置和跟踪“命令”(如 _trackPageview)推送(附加)到队列的末尾。您的命令将存储在此数组中,直到 ga.js 完全下载。

当 ga.js 准备好时,它会执行 _gaq 数组中的所有命令,并将 _gaq 替换为一个对象。这个对象也有一个 push 方法,但它不是排队命令,而是立即执行它们,因为 ga.js 可以处理它们。

这种机制可以让你在不知道浏览器是否已经下载完 ga.js 的情况下进行配置和跟踪命令。这是必需的,因为异步代码段下载 ga.js 时不会阻止页面上的其他代码运行。如果其他代码(您的配置命令)需要知道正在下载的 ga.js 的状态,事情就会变得棘手。

所有这一切都完全依赖于使用的名称_gaq的。如果您希望异步跟踪工作,您不应该尝试命名它。

是的,它确保_gaq已定义,因此_gaq.push()永远不会失败。

我不会弄乱 GA 代码中变量的名称......你有什么理由吗?它是否与您的任何变量冲突?(然后我会改变我的......)

我对“_gaq”本身没有问题,但我在谷歌分析文档中没有发现关于有一个名为 _gaq 的变量的警告。
2021-04-27 23:15:56
好吧,如果 Google 确实发出了有关使用 _gaq 变量的警告,您会不会想尝试一下?就像robots.txt:如果你能读懂它,并且它包含一行Disallow: /admin/,你会不会尝试在URL中添加“/admin/”来看看它做了什么?
2021-04-27 23:15:56
没有文档说你不应该有一个名为 _gaq 的变量,但如果你想使用 GA(包括非异步版本),你应该避免使用该命名空间。
2021-05-07 23:15:56
如果 _gaq 之前声明过但不是数组而是数字或字符串,它仍然会失败:)
2021-05-09 23:15:56
这就像对黑客的公开邀请,比如 robots.txt。您可以将“请不要使用 xxx”解释为“当您使用 xxx 时,我们的代码容易受到攻击”。:-)
2021-05-19 23:15:56

||在赋值中使用是一种常见的编程技巧,它利用运算符的评估方向,即从左到右。这意味着它首先评估左侧。然后,并且仅当它是假的(或假的等价物)时,它才会评估右侧。

您还可以在简单的 if 语句中利用||or&&运算符,以便

if (a > 5) {
  do_a();
}

if (!some_boolean) {
  do_b();
}

变得

a > 5 && do_a();
some_boolean || do_b(); // Note that the negation operator `!` is gone!

这两种方式都更好看。

语言允许这样做的原因是,如果左侧无论如何都会使整条线失败,那么评估右侧就是浪费时间。因此,除非需要,否则它只会忽略它。

我更喜欢你的例子中的 if 语句,更易读。
2021-05-09 23:15:56

抱歉回答晚了,但我阅读了已接受的答案,我认为它错过了最重要的事情。所以我会试着解释我的理解:

首先,已经解释了,但答案需要完整,所以我也解释一下,代码开头:

var _gaq = _gaq || [];

它确保 _gaq 已定义。如果未定义,则将其初始化为空数组。

把它想象成等价的:

var _gaq;
/* ... */
if(!_gaq)
  _gaq = [];

javascript 值undefined是“falsish”/“falsy”,即它在转换为布尔值时评估为false,因此[] 在这种情况下初始化_gaq

需要注意的是:

  • 如果 _gaq 在此阶段包含一个数组,则 _gaq 是“真实的”,因此它将保留它的值(并且不会被清空)
  • 如果_gaq在这个阶段包含另一种类型的对象,_gaq也可以保持它的值

好吧,我尽可能地重新解释了已经解释过的内容。大多数使用过 javascript 的人已经理解了它。然而,有趣的部分不仅仅是开始!

_gaq.push(['command', 'argument']); // is very interesting too

如果 _gaq 是一个数组,大家都会猜到这个 item['command', 'argument']是追加到数组中的。谷歌分析将其存储在其队列中以供进一步处理。数组 _gaq 用作队列。

但真正有趣的部分是_gaq.push(/*...*/)可以在没有名为 _gaq 的数组的情况下完成。它只是一个方法调用,非数组也可以有一个“ push”方法。

它“开辟了新的可能性”。这是一个总结:

  • 只要不异步加载外部javascript文件,_gaq就是一个用作队列的数组。
  • 然后外部 ga.js 处理队列。
  • 然后 ga.js 将 _gaq 替换为一个提供 push 方法的对象。
  • 一旦 _gaq 被一个对象替换,_gaq.push(/*...*/)命令就不需要再延迟了,它们可以被执行。

对于那些错过了异步脚本加载部分的人来说,它是:

(function() { 
  var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; 
  ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; 
  var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); 
})();

临时使用数组作为队列和 push 方法是很棒的代码。这是一种非常有趣的方式来处理这样一个事实,即在_gaq.push(/*...*/)执行时,我们并不总是现在是否已经异步加载依赖项。

管理此类问题的另一个相关有趣的方法是新的 Google Analytics“isogram”片段ga(/*...*/)看起来更直观的调用 that _gaq.push(/*...*/),但它仍然以异步方式处理与加载依赖项相关的乐趣。

谁能解释一下这是干什么用的?

我希望我上面的回答已经做到了。我想在这里分享的是,第一行以一种特殊的方式完成以适应整个事情:如果完成两次就不会伤害初始化,巧妙地使用推送方法......

Google Analytics 是否依赖名为 _gaq 的全局对象?

是的,当使用这个 ga.js 片段时。

编辑:

我会添加更多细节

_gaq 只是一个 javascript 数组,正如最初定义的那样。您向其添加事件,例如事件跟踪回调

但是,当加载 ga.js 脚本时,google 会获取此数组并将其转换为 ga 使用的对象。

这就是为什么你将函数推入 _gaq 数组,然后在你完成构建数组之后调用 ga.js 脚本。

gaq 是谷歌分析队列。它是 GA 方法的堆栈,例如事件跟踪、页面归​​因等。您可以使用 push() 方法将 GA 内容放在那里。减少事件干扰,每个人都应该这样做,或者至少学习这个概念。