什么是"var _gaq = _gaq || [];"for?

46 javascript google-analytics

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); 
})(); 
Run Code Online (Sandbox Code Playgroud)

关于第一行:

var _gaq = _gaq || []; 
Run Code Online (Sandbox Code Playgroud)

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

任何人都能解释这是为了什么吗?

此外,_gaq重命名是否重要?换句话说,Google Analytics是否依赖于名为_gaq?的全局对象?

Bri*_*ian 25

此行允许在同一页面中包含多个GA代码段.它确保第二个片段不会覆盖第一个片段定义的_gaq.

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

当ga.js准备就绪时,它会执行_gaq数组中的所有命令,并用对象替换_gaq.此对象还有一个push方法,但它不是排队命令,而是立即执行它们,因为ga.js可用于处理它们.

此机制允许您在不知道浏览器是否已完成下载ga.js的情况下进行配置和跟踪命令.这是必需的,因为异步代码段会下载ga.js而不会阻止页面上的其他代码运行.如果其他代码(您的配置命令)需要知道正在下载的ga.js的状态,事情就会变得毛茸茸.

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


Vic*_*tor 15

是的,它确保_gaq定义,以便_gaq.push()永远不会失败.

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

  • 如果之前声明_gaq但它不是数组而是数字或字符串:)它仍会失败 (4认同)
  • 没有文档说你不应该有一个名为_gaq的变量,但是如果你想使用GA(包括非异步版本),你应该避免使用那个命名空间. (3认同)

Tor*_*amo 13

||在赋值中使用是一种常见的编程技巧,它利用了从左到右的操作符的评估方向.这意味着它首先评估左侧.然后,只有当它是假的(或错误的等价物)时,它才会评估右侧.

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

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

if (!some_boolean) {
  do_b();
}
Run Code Online (Sandbox Code Playgroud)

成为

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

这两种方式都更好看.

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


dot*_*ush 5

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

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

var _gaq = _gaq || [];
Run Code Online (Sandbox Code Playgroud)

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

把它想象成等价的:

var _gaq;
/* ... */
if(!_gaq)
  _gaq = [];
Run Code Online (Sandbox Code Playgroud)

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

需要注意的是:

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

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

_gaq.push(['command', 'argument']); // is very interesting too
Run Code Online (Sandbox Code Playgroud)

如果 _gaq 是一个数组,大家都会猜到该项['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); 
})();
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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

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