Monday, September 18, 2017

syntactic high-fructose corn syrup

It's easy for old fogies like me to get a bit cynical about ES6 and all the new syntactic sugar - it can be tough to pick up because if you've only seen it in a webinar or two, but it's not prevalent in the legacy code base you're working with daily, it's easy to forget, and then confusing when you do run into it.

Case in point, this line:
const { urls = {} } = window || {};

Roughly it's saying "set a constant variable (ok, a 'constant') called urls to window.urls if it exists, but don't blow up if window or window.urls doesn't exist."

Besides recognize const vs var, there are three things going on in that tangle:
  1. The good old fashioned, pre-ES6 "short circuit" operator, where you can say
    something = thatthing || {};
    so the right side is thatthing if thatthing is truthy-true otherwise, set to an empty map.

    (huh, surprised the people who love triple equals haven't made triple-or to specifically handle "if this is null or undefined")
  2. Destructuring! The simple case here would be if you had an object called foo with a key bar set to something and a key baz set to something. Then you could say
    var {bar,baz} = foo;
    to get a local var bar and a local var baz set to foo.bar and foo.baz, respectively.

    This actually neatly addresse a weird asymmetry in C-style syntax I blogged about 13 years ago - that it's strange that you pass many things into a function, but you only get one thing out. But now you can do
    var {oneThing, anotherThing} = someFunctionCall();
    and you don't have extract simple variables out of a map object by hand.
  3. Default parameters - for a second
    {urls = {}}
    seemed so strange... I mean I see the value of saying "set urls equal to this if all else fails" but was it a special, one-off syntax just for destructuring? Well, no, now that I think about it... in ES6 you can have
    function someFunc(someParamWithADefault="that default"){ 
    and if nothing is passed in for that first parameter, the first parameter becomes that default. And so we see the syntax used inside the destructuring assignment is borrowing from that generalized default parameter shortcut
So thanks to Dan at work who wrote the code and then explained it to me nicely when asked... he also pointed out I can go to this Babel.js tool to see the concise syntax translated into old school javascript.... in this case
  const { urls = {} } = window || {};becomes

"use strict";
var _ref = window || {},
    _ref$urls = _ref.urls,
    urls = _ref$urls === undefined ? {} : _ref$urls; 
Still a little tough to digest, but it's nice to be able to trace the steps. 

So it seems like Javascript is borrowing the Perl idea of "lets say this more concisely with nifty syntaxes!" but missing Perl's "lets not blow up if we try to pull a value out of an object that doesn't really exist". 

1 comment: