gpt4 book ai didi

javascript - 为什么 Segment.io 加载程序脚本将方法名称/参数推送到一个看似被覆盖的队列中?

转载 作者:数据小太阳 更新时间:2023-10-29 04:00:20 31 4
gpt4 key购买 nike

我一直在剖析以下代码片段,它用于异步加载 Segment.io分析包装器脚本:

// Create a queue, but don't obliterate an existing one!
var analytics = analytics || [];

// Define a method that will asynchronously load analytics.js from our CDN.
analytics.load = function(apiKey) {

// Create an async script element for analytics.js.
var script = document.createElement('script');
script.type = 'text/javascript';
script.async = true;
script.src = ('https:' === document.location.protocol ? 'https://' : 'http://') +
'd2dq2ahtl5zl1z.cloudfront.net/analytics.js/v1/' + apiKey + '/analytics.min.js';

// Find the first script element on the page and insert our script next to it.
var firstScript = document.getElementsByTagName('script')[0];
firstScript.parentNode.insertBefore(script, firstScript);

// Define a factory that generates wrapper methods to push arrays of
// arguments onto our `analytics` queue, where the first element of the arrays
// is always the name of the analytics.js method itself (eg. `track`).
var methodFactory = function (type) {
return function () {
analytics.push([type].concat(Array.prototype.slice.call(arguments, 0)));
};
};

// Loop through analytics.js' methods and generate a wrapper method for each.
var methods = ['identify', 'track', 'trackLink', 'trackForm', 'trackClick',
'trackSubmit', 'pageview', 'ab', 'alias', 'ready'];

for (var i = 0; i < methods.length; i++) {
analytics[methods[i]] = methodFactory(methods[i]);
}
};

// Load analytics.js with your API key, which will automatically load all of the
// analytics integrations you've turned on for your account. Boosh!
analytics.load('MYAPIKEY');

评论很好,我可以看到它在做什么,但是当涉及到 methodFactory 函数时,我感到很困惑,它推送在主 analytics.js 脚本已加载到全局 analytics 数组。

一切都很好,但是如果/当主脚本确实加载时,它似乎只是覆盖了全局analytics变量(参见last line here),所以所有数据都将丢失。

我看到这是如何通过清除尚不存在的方法来防止网页中的脚本错误的,但我不明白为什么 stub 不能只返回一个空函数:

var methods = ['identify', 'track', 'trackLink', 'trackForm', 'trackClick',
'trackSubmit', 'pageview', 'ab', 'alias', 'ready'];

for (var i = 0; i < methods.length; i++) {
lib[methods[i]] = function () { };
}

我错过了什么?请帮助我理解!

最佳答案

Ian,Segment.io 的联合创始人——我实际上并没有编写该代码,Calvin 写了,但我可以告诉你它在做什么。

你是对的,methodFactory 将方法 stub ,以便它们在脚本加载之前可用,这意味着人们可以调用 analytics.track 而无需包装这些方法在 ifready() 调用中调用。

但这些方法实际上比“愚蠢的” stub 更好,因为它们保存了被调用的方法,因此我们可以稍后重放操作。这是这部分:

analytics.push([type].concat(Array.prototype.slice.call(arguments, 0)));

为了提高可读性:

var methodFactory = function (method) {
return function () {
var args = Array.prototype.slice.call(arguments, 0);
var newArgs = [method].concat(args);
analytics.push(newArgs);
};
};

它附加了被调用方法的名称,这意味着如果我analytics.identify('userId'),我们的队列实际上会得到一个如下所示的数组:

['identify', 'userId']

然后,当我们的库加载时,它会卸载所有排队的调用并将它们重播到实际方法(现在可用)中,以便仍然保留加载前记录的所有数据。这是关键部分,因为我们不想丢弃在我们的库有机会加载之前发生的任何调用。看起来像这样:

// Loop through the interim analytics queue and reapply the calls to their
// proper analytics.js method.
while (window.analytics.length > 0) {
var item = window.analytics.shift();
var method = item.shift();
if (analytics[method]) analytics[method].apply(analytics, item);
}

analytics 是此时的局部变量,在我们完成重放后,我们用局部 analytics 替换全局变量(这是真正的交易)。

希望这是有道理的。实际上,我们将在我们的博客上发布一系列关于第 3 方 Javascript 的所有小技巧,所以您可能很快就会了解它!

关于javascript - 为什么 Segment.io 加载程序脚本将方法名称/参数推送到一个看似被覆盖的队列中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14859058/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com