Can you explain to me what's going on in this code?

twitter logo github logo ・1 min read

In trying to understand a Google snippet I had the thought that it might be an interesting type of discussion—explaining a code snippet.

This code is minimized for efficiency. Anyone care to read this to me?

<style>.async-hide { opacity: 0 !important} </style>
<script>(function(a,s,y,n,c,h,i,d,e){s.className+=' '+y;h.start=1*new Date;
h.end=i=function(){s.className=s.className.replace(RegExp(' ?'+y),'')};
(a[n]=a[n]||[]).hide=h;setTimeout(function(){i();h.end=null},c);h.timeout=c;
})(window,document.documentElement,'async-hide','dataLayer',4000,
{'GTM-PNDQRRW':true});</script>
twitter logo DISCUSS (9)
markdown guide
 

TLDR: What this snippet does is assign a class, namely 'async-hide' to the <html> element of our document, waits 4 seconds, and then removes it.

We have a self running function with a bunch of parameters but let's "prettify" it first.

(function (a, s, y, n, c, h, i, d, e) {
    s.className += ' ' + y;
    h.start = 1 * new Date();
    h.end = i = function () {
        s.className = s.className.replace(RegExp(' ?' + y), '')
    };
    (a[n] = a[n] || []).hide = h;
    setTimeout(function () {
        i();
        h.end = null
    }, c);
    h.timeout = c;
})(window, document.documentElement, 'async-hide', 'dataLayer', 4000, { 'GTM-PNDQRRW': true });

Hmmm. That didn't help much. Okay. Let's replace all the parameters with their actual variables.

(function (h, i, d, e) {
    document.documentElement.className += ' ' + 'async-hide';
    h.start = 1 * new Date();
    h.end = i = function () {
        document.documentElement.className = document.documentElement.className.replace(RegExp(' ?' + 'async-hide'), '')
    };
    (window['dataLayer'] = window['dataLayer'] || []).hide = h;
    setTimeout(function () {
        i();
        h.end = null
    }, 4000);
    h.timeout = 4000;
})({ 'GTM-PNDQRRW': true });

Much better. Now we have left the options object being passed as h, i only being used as variable declaration, and d and e are unused other than making the original parameter list async hide.

  • document.documentElement represents the <html> element
  • .className += ' ' normalizes our variable to a String and is setting the class attribute on `
  • + 'async-hide'; sets the class to async-hide which will be used later.
  • h.start = 1 * new Date(); sets on our options Object a time 1 second from now
  • h.end = i = function () sets the end property and assigns our i parameter a value
  • document.documentElement.className = document.documentElement.className.replace(RegExp(' ?' + 'async-hide'), '') really convoluted way to remove only the async-hide class from <html>
  • (window['dataLayer'] = window['dataLayer'] || []) grabs the dataLayer list from Google Tag Manager or returns an empty Array
  • .hide = h; sets the hide property to out options object
  • i(); calls our function to remove the class
  • h.end = null removes the reference to our function from the options object
  • h.timeout = 4000; the snippet waits 4 seconds before doing anything

So.

What this snippet does is assign a class, namely 'async-hide' to the <html> element of our document, waits 4 seconds, and then removes it.

Addendum, and I almost forgot! The CSS makes the entire document invisible. Presumably to wait for the page to load and hoping everything is done by then so as to not get a FOUC or similar.

 

1*new Date() turns the date object into an integer.

 

I tried to un-minimize it. Not all the way there, but at least now it's easier to see what the code is doing. 😁

const docElem = document.documentElement;
docElem.className += ' ' + 'async-hide';

const removeHideClass = function() {
  docElem.className = docElem.className.replace(/ ?async-hide/, '');
}

const hide = {
  'GTM-PNDQRRW': true,
  start: 1*new Date,  // new date (in seconds)
  end: removeHide
};

// window.dataLayer seems to be where Google Tag manager stores data to track

// Load or initialize it to an empty array
window['dataLayer']=window['dataLayer'] || [];
window['dataLayer'].hide = hide;

setTimeout(function() {
  removeHideClass();
  hide.end = null;
}, 4000);

hide.timeout = 4000;
 

Totally cheated, but this explainer for it is pretty good. It hides the page content until the Optimize container is loaded in. Hilarious that they added those extra parameters in to write out asynchide though!

 

On load, the entire page is hidden. Meanwhile, it's checking after 4 seconds for GTM's dataLayer global variable to be set. When it's available, it'll remove the .async-hide class to show the page.

And it looks like the i, d, and e are dummy arguments just there to do something cute like making it spell out asynchide 🤔

I'm a bit less sure why it's only waiting 4 seconds before the check though.

 

Here's my stab at it without running the code.

So the style is to set an element to opacity: 0 no matter what because of the !important. It does this on the root element of the document document.documentElement by appending the CSS class async-hide via s.className+=' '+y, where s is `document.documentElement.

Then it adds a property start who's value is 1*newDate to the object being passed in {'GTM-PNDQRRW':true} which is represented by the parameter h in the anonymous immediately invoked function. It also sets an end property on the same object whose value is a function function(){s.className=s.className.replace(RegExp(' ?'+y),'')};

After that it sets a global var on the window, parameter a, via a[n], where n is 'dataLayer'. It sets itself to itself if it exists, otherwise it's initialized to an empty array, (a[n]=a[n]||[]). On window.dataLayer (from a[n]), it sets a hide property which is equal to the object h, the enhanced {'GTM-PNDQRRW':true}, object.

From there a setTimeout is invoked which fires after 4000 milliseconds (taken from the parameter c. Inside the timeout, it runs the function i which is the same reference as the function h.end. Once i() has run, it's set to null via h.end = null. While the timeout is set to run in 4 seconds, the enhanced object represented by h gets a timeout property whose value is c (4000ms).

I'm assuming because of GTM in the object key that this is some Google Tag Manager voodoo?

So all in all what does this do? It looks like it hides document.documentElement and then removes the CSS class that had it's opacity set to 0 for 4 seconds and this action seems to be related to this 'GTM-PNDQRRW'.

 

a,s,y,n,c,h,i,d,e

The function doesn't use d or e variables. Somebody is just being cute.

 

Going by the name it hides an element by setting the opacity to 0.

 

Looks like it assigns a class name to an element for 4 seconds!

Classic DEV Post from May 24

ECMAScript Classes - Keeping Things Private

Ben Halpern profile image
A Canadian software developer who thinks he’s funny.