Про инициализацию счетчиков Яндекс Метрики и Google API
Яндекс Метрика
(function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
m[i].l=1*new Date();k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)})
(window, document, "script", "https://mc.yandex.ru/metrika/tag.js", "ym");
Из необычного используется оператор запятая, эквивалентно:
window.ym = window.ym || function() {
window.ym.a = window.ym.a || [];
window.ym.a.push(arguments);
};
window.ym.l = 1 * new Date();
const script = document.createElement('script');
const firstScript = document.getElementsByTagName('script')[0]; // первый <script> в текущем документе
script.async = 1;
script.src = 'https://mc.yandex.ru/metrika/tag.js';
firstScript.parentNode.insertBefore(script, firstScript);
Как нетрудно заметить, у метрики 6 и 7 параметры (k, a) в момент вызова undefined
т.е. это своего рода инициализация, чтобы в дальнейшем присвоить document.createElement('script')
и document.getElementsByTagName('script')[0]
соответственно.
Google API
(function(w,d,s,g,js,fjs){
g=w.gapi||(w.gapi={});g.analytics={q:[],ready:function(cb){this.q.push(cb)}};
js=d.createElement(s);fjs=d.getElementsByTagName(s)[0];
js.src='https://apis.google.com/js/platform.js';
fjs.parentNode.insertBefore(js,fjs);js.onload=function(){g.load('analytics')};
}(window,document,'script'));
Эквивалентно:
window.gapi = window.gapi || (window.gapi = {});
window.gapi.analytics = {
q: [], // очередь функций обратного вызова, которые будут выполнены, когда загрузится библиотека
ready: function(cb) {
this.q.push(cb);
},
};
const script = document.createElement('script');
const firstScript = document.getElementsByTagName('script')[0];
script.src = 'https://apis.google.com/js/platform.js';
firstScript.parentNode.insertBefore(script, firstScript);
script.onload = function() {
window.gapi.load('analytics'); // нужное API, в данном случае аналитика
};
Немного объяснений
Используется IIFE, что позволяет избежать конфликта используемых имён переменных.
(function(_, global, document) {
// use _ for library, global for window
// code
}(library, window, document));
Код исполняется также как и без (function(_, global, document) { ... }(library, window, document));
, но не загрязняется глобальная область. Также код экранируется от того, что кто-то может случайно изменить используемые переменные.
Лично я до конца не в курсе зачем передавать window
и document
как параметры, но в этих ваших интернетах пишут следующее:
- Локальные переменные разрешаются быстрее, чем глобальные т.к. ссылки в IIFE не нужно искать за пределами локальной области видимости.
- Минификаторы JavaScript могут безопасно минимизировать имена параметров, объявленные в функции.