Thursday, November 10, 2016

ES6 review, part-2

Continuing (belatedly) from the previous review of some new language features of Javascript ES6.  Again, based upon ES6 & Beyond by Kyle Simpson  (O'Reilly, (c) 2016) and using chess annotations (!, ?, etc.) to rate the features.

Concise Properties!

Saves typing, especially if you use long, informative variable names, which encourages their use, which is a very good thing.  However, I'm a little concerned in all of these "shortcuts" about typos and or accidentally polluting the global name space.

Concise Methods!?

A shorter way to create function expressions.  The whole expression vs. declaration stuff gives me a headache, and, coming from a Java "like classes" background I tend to use the later.  So not sure how much I'll use the new feature.  

Also, these concise method expressions fall apart (and are tricky to debug) when you are nested deep withing other functions then calling things recursively.  To which I say don't do that!  The code for which they fail is extremely complex code which is probably best refactored.

Getter / Setter ?

I'm torn on this one.  Obviously, coming from a Java background, I like the concept.  However, I also like explicitness, and operator overloading is confusing and generally held to be a bad thing.  With the new getters/setters, when I go

   var x = foo.bar;

I don't know if this is simple trivial property lookup (which it sure looks like!), or this is calling a function that will spend 10 minutes calculating pi, then become self-aware and launch Judgement Day.  Following Zen of Python, Rule #2: "Explicit is better than implicit", I think it's preferable to show the function call:

   var x = foo.getBar();

Computed Property Names?!

Meh, again not so sure.  If I have a lot of properties (or methods) starting with "Hillary-", and another set with "Trump-", do I want them all mixed into a single object, or isn't it simpler to subdivide and have

var foo = {
   Hillary: {
      party: "democrat",
      taxes: function() { ... }
   },
   Trump: {
      party: "yes",
      taxes: function() { return undefined; }
   }
}


and access them via

  foo[name][property]?

I don't see any great advantage is mixing them all together with foo[name+property].  However, they are used a lot for symbols, and can be useful for concise methods and generators, so I'll keep my mind open.


Super!

hard to argue much with this.

Template Literals (a.k.a. Interpolated String Literals)

I agree with the complaint that these aren't "templates" in the sense that many use them.  They aren't Mustache, JADE, whatever.  However, the ability to use

"Hello ${firstname} ${lastname}!"

instead of

"Hello " + firstname + " " + lastname + "!";

strikes me as a very very good thing.  One can also put functions inside the braces, which, if used with discretion, is also great.

"Hello ${decodeURI(nameFromAForm)}"

Arrow Functions

I'll talk more later about these.  He does point out a lot of "gotchas" and limits the cases where they should be used.

for..of Loops!!

Why did it take a gazillion years to add this obviously great feature?  Yes, I guess the functional guys will say you could use forEach, but this is simpler for most.



Notes

Astute readers will note that I'm not using prism.js for syntax highlighting.  Seems to work well.  However, it's tedious in Blogger to go to HTML edit mode, and when I'm there I see that the HTML code is a disaster of crapola so it's hard to find the code you just types to surround it by the pre and code tags.  I'm going to start playing with Ghost and this blog is likely to migrate there soon.  And Blogger constantly changing my font size is just so annoying.









Friday, May 6, 2016

ES6 Review, part-1

This is a first post reviewing the new features of JavaScript ES6.  It is also a short review of ES6 & Beyond, by Kyle Simpson (O'Reilly, (c) 2016), which I'm using to learn most of the new stuff.  Also on GitHub.  I will rate things using chess annotations, where an exclamation mark is "good" and a question mark is "dubious".

As for my background and biases, for 20+ years I was a traditional desktop app programmer, mainly in C and Java.  I'm fairly new (~4 years) to JavaScript.  I often appreciate, but sometimes hate, the differences between it and Java.  I've used NodeJS and some of its most common modules (Express, Request), but otherwise, have used few of the mainstream JS libraries such as JQuery and Angular.


Intro

The book is moderate sized (~260 pages, trade paperback sized (6" x 9")) and meets O'Reilly's typical high standards for fonts, printing, binding etc. It's a little disappointing that they ran out of the traditional animal pictures to put on the covers.  :-)


Let's start with Chapter 2, which covers new Syntax.  There's a lot.

Block Scoping!!

Welcome to the 20th century JavaScript.  Anything that reduces the need for an IIFE hack is a plus in my book.

Let!!

Instead of var x, which is subject to the occasional bugs of hoisting, or polluting namespaces, using let x declares the variable with block scope from that point forward, much like C and Java.  Using that variable before it's declaration results in a ReferenceError from a "Temporal Dead Zone" (TDZ).  This sounds confusing and the terminology is off-putting, but the simple answer is to declare your variables before using them!  Just like almost every other language.

Unfortunately, the author goes off on a multi-page tangent describing his preferred version for let syntax, which is less conventional and differs from  C/Java tradition.  Since this alternate syntax was not adopted by ES6, the discussion is confusing and useless.  In general, I like the opinions expressed by Mr. Simpson in the book, but here was one case where he went off base.

Let with a For Statement!

A minor benefit of let over var in a loop is that let redeclares the variable each iteration, so it is "sticky" if used in a callback.  Mr. Simpson provides a precise and clear example of this benefit.

const!

Immutability has many advantages, and in ES6 declaring a variable const makes this clearer.  Note that in the case of a reference to an object, say an array, only the reference is immutable, not the contents of the array.  That limitation is unfortunate but the same as many other languages.  Mr. Simpson provides a concise and clear example.

Block Scoped Functions

Meh, o.k. If you write a lot of complex recursive stuff it's useful, but I don't see a huge need for this in typical code, and there are some incompatibility issues.

Spread!  Rest (a.k.a. "Gather")!!

Both of these use "..." in your code, which might be slightly confusing at first, but I think in practice you'll get used to it, and it mimics existing C and Java syntax, so it was a good choice.

When ... is used before an iterable (see later), such as an array, it "spreads out" the individual elements of that iterable.  Mr. Simpson provides nice examples of how this can be used to conveniently replace apply() or concat().

In alternative places, ... gathers a group of variable into an array.  The book calls this "rest" because it is gathering "the rest of the arguments".  I'd much prefer "gather" or "varargs".  Since a great place to use this syntax is to gather any variable arguments passed to a function at the end of the argument list.  e.g.

function foo(a, b, ...varargs) {}

This mimics behavior in other languages such as Python and Java.  Note that a common use case will be to rewrite code that used the deprecated "array-like" arguments array.  Instead of chanting the mantra "Array.prototype.slice.call":

function foo() {
  var args = Array.prototype.slice.call(arguments);
  // now args is a real array
}

Just do

function foo(...varargs) {
}

Note: This is not explicitly mentioned in the book, but if there are no "rest of" arguments to gather, varargs will be set to an empty array, not undefined.  IMO this is correct behavior.


Default Parameter Values!

These are superior to streams of
   x = x || 6;
in your code.

You can also call functions or invoke an IIFE in your default, but, IMO, this is probably getting too complex or cute.  The book hints at this and details several "gotchas".  But one nice use-case is to provide a default "do nothing" callback function in your function declaration, e.g.

function asyncFoo(url, callback=function(){}) {
}


Destructuring ?!

Have to say, I don't see the point in this, the book doesn't provide any "killer use cases", and it's confusing.  If anybody does have a killer use case, please let me know.  Until then, count me a skeptic.

Let's say a function returns multiple results, e.g. in an array or an object.

function get3DCoordinates() { 
  return [1,2,3]; 
}

function getLocation() {
  return {
     lat : 1;
     lon : 2;
  }
}


Before ES6, you'd go

var c3 = get3DCoordinates();
// use c3[0], c3[1], c3[2]as needed...

or

var loc = getLocation();
// use loc.lat, loc.lon as needed...


With ES6, you can go

var [x,y,z] = get3DCoordinates();
// use x, y, z instead...

or

var { lat: lat, lon:lon } = getLocation();
// use lat, lon instead...


The syntax with the variables on the left is a bit confusing, but I could get used to it.  Fundamentally, I question this usefulness of this.  When a function returns multiple values, those values usually belong together.  If they don't belong together, why is a single function returning them?  You are likely violating the Single Responsibility Principle.

What's the advantage of splitting apart things that belong together?

An another counterexample, what if you needed the location of two things?  What looks like better code to you?

var sanFran = getLocation(94101);
var seattle = getLocation(98101);
var dLat = sanFran.lat - seattle.lat;
var dLon = sanFran.lon - seattle.lon;

or

var { latSF, lonSF } = getLocation(94101);
var { latSeattle, lonSeattle} = getLocation(98101);
var dLat = larSF - latSeattle;
var dLon = lonSF - lonSeattle;

I prefer the old fashioned approach, but maybe your mind works differently.  What if you need the location of N things?

Pages 26-38 of the book cover many more complex cases of destructuring.  With, IMO, no killer use case.  For example, is

var { model : { User } } = App;

really any improvement over

var User = App.model.User;

No.  The new syntax is confusing, it's more typing (in this case), and, most importantly, it's very complex syntax in the typing.  Instead of a couple of dots, flowing left to right, in standard western 1,2,3 order, as we are all used to, you have to properly nest brackets, and the order of the fields is all mixed up - not even reversed, the order is 2,3,1!  The programmer has to think, usually a bad thing.

Until I see a good use case for destructuring, it seems like a confusing addition to the language with little usefulness.  Mr. Simpson provides an example where you can combine preferences/settings from two different objects, e.g. user-preferences and default values.  However, the example only works if you know ahead of time (and put in the code) all of the possible fields.  In my experience, preferences expand over time and come from different projects, so this would be difficult or impossible to maintain.  Without a good use case, I don't see much value in destructuring.  What do you think about it?

Next time, we will continue with even more syntax changes, starting with Object Literal Expressions.  See you then.







Thursday, March 24, 2016

Learning Google Maps

Inspired by the upcoming Race to Alaska, I put together a web page that integrates the nice JSON weather reports from the OpenWeatherMap API, plus some XML format reports from NOAA buoys.  These get drawn on a map with wind barbs.  You can scroll around to see various areas on the map, and click on a station to get more details.

It tracks the recent reports and attempts to compute an hourly rate of change for some statistics.  Depending on the time between reports this can be an inexact science.  But it helps to see if wind, pressure or temperature is changing rapidly.

The back end code is written in JavaScript using Node.js.  The front end is HTML and JavaScript and the Google Maps Javascript API.