Про инициализацию счетчиков Яндекс Метрики и 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 могут безопасно минимизировать имена параметров, объявленные в функции.

Похожие записи

Поисковый запрос с помощью RxJS

Показательная и востребованная задача. Получение набираемого запроса из поля ввода через полсекунды после того, как пользователь закончил ввод с показом лоадера.