skip to Main Content

When updating Google Tag Manager to support CSP and nonce, they say to use this script:

(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;var n=d.querySelector('[nonce]');
n&&j.setAttribute('nonce',n.nonce||n.getAttribute('nonce'));f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-XXXXXX');

The n&&j.setAttribute() is confusing to me; not sure if it’s just a lack of Javascript knowledge or something else weird going on here. n and j are both Html Elements. setAttribute() adds the nonce attribute to element j and has no return value. What does the n&& do or mean? Doesn’t this just take the "and" of element n and the return value of setAttribute? But then it doesn’t do anything with the value of that and?

Or, is it that n&&j is actually evaluated first, and this script actually calls setAttribute on both n and j? That seems like a weird behavior to me if it does.

When I paste this code into Visual Studio, it automatically adds some whitespace. I was assuming that n && j.setAttribute() is the same as n&&j.setAttribute() but are they actually different?

2

Answers


  1. It’s taking advantage of short-circuiting of the boolean operators to implement a conditional in the shortest syntax. This is the result of a code minifier — they replace all the variable names with short, meaningless names and use as compact syntax as possible (including omitting any unnecessary whitespace); the code isn’t intended to be easily understood.

    In this context it’s effectively equivalent to:

    if (n) {
        j.setAttribute(...);
    }
    

    There’s no difference between n&&j.setAttribute() and n && j.setAttribute(). Whitespace has no significance between tokens in JavaScript. The . operator has higher precedance than &&, so it’s always interpreted as

    n && (j.setAttribute())
    

    So VS Code was correct to reformat it that way, to make it more readable.

    To get what I think you thought may have been intended, you need to add parentheses:

    (n && j).setAttribute()
    

    But that’s not what the original code was doing.

    Login or Signup to reply.
  2. It’s just the regular old Logical AND.

    This works by using the fact that JS evaluates the && lazily.

    So if the left side is falsy, the right side won’t get evaluated at all (i.e.: a method there won’t be called) since the result of the binary logic operation is already clear: false.

    But if the left side is truthy, logic dictates that the right side also needs to be evaluated to get to the correct result.

    That the result isn’t even used doesn’t bother JS 🙂

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search