JavaScript for Data Analysts

Me

  • Software Engineer at Urban Center for Computation and Data
  • willengler@uchicago.edu
  • Lincoln in the Bardo by George Saunders lives up to the hype

Goals

  • Know the basics of JavaScript, and how it's used
  • Give you enough context such that if you ever need to write JS, you can dive in effectively.

Outline

  • History
  • Language tour
  • Effective asynchronous JS
  • Data visualization

JavaScript's Torrid History

1995: A War for the Browser

  • Sun was pushing Java applets for rich applications over the internet
  • Netscape wanted to support a Hypercard-like model where a scripting language could be used within web pages

And on the 10th Day...

  • Netscape hired Brendan Eich to write a Scheme interpreter (or so he thought)
  • The new language needed to ride the Java and object-oriented hype train
  • After 10 DAYS of development, JavaScript was born.

"A LISP in C's Clothing"

  • Java: Curly brace syntax  (C/ALGOL style)
  • Scheme: Functions
  • Self: Prototypal inheritance

2005: The Invention of AJAX

  • Google's Gmail and Maps start blurring the boundaries between web pages and web applications
  • A seminal blog post coins the term AJAX: asynchronous JavaScript and XML
  • AJAX wasn't new tech - just a design pattern

2008: The V8 Engine Debuts

  • V8 engine debuts with Google Chrome
  • Previous JS engines were interpreted
  • V8 is JIT compiled and contains many other clever optimizations

V8 Spreads

  • 2009: Node.js
    • Single-threaded runtime targeted to network bound server applications
  • 2010: Node Package Manager (NPM)
  • 2013: Electron
    • Framework for desktop applications - used by Atom, Slack, Visual Studio Code

A Language Tour

How to Start Playing with JS

  • Easiest: Open your browser's dev console
  • A little effort: Write a .html file, embed some JS in a <script> tag, and open the file in a browser
  • Getting serious: Install Node on your system

Objects

// Objects are collections that map strings
// to values of any type
var myObject = {
    foo: 1
    bar: 'fizz'
}

// String dereference
myObject.foo // 1

// Expression dereference
myObject['b' + 'ar'] // fizz

// Attribute assignment
myObject.bar = 'gorp'

Functions

// Function statement
function add(a, b) {
    return a + b;
}

// Function expression (anonymous function AKA lambda)
function(a, b) {
    return a + b;
}

// Functions are "first class"
// (you can create them and pass them around dynamically)
// and close over their parent function's scope
function makePrinter(message) {
    return function() {
        console.log(message)
    }
}
var printUpbeatMessage = makePrinter("Isn't JS dandy?")
printUpbeatMessage() // "Isn't JS dandy?"

Bear in mind that it was made in 10 days

Unfortunate features

Over-eager type coercion

2 == '2' // true!?!?
2 === '2' // false
// Lesson: you almost always want to use the === operator for equality checks
// == coerces, === does not

undefined and null

var myObject = {
    foo: null
}
var a = myObject.foo // null
var b = myObject.bar // undefined
Boolean(a) // false
Boolean(b) // false

Standards Improvements

  • Conflict between browser vendors long stood in the way of improving JavaScript standards (ECMAScript or "ES")
  • 2009: ES5
  • 2015: ES6
  • The latest standards help you avoid some of the weirder parts of the language

"Don't Break the Web"

  • New syntax added while preserving old syntax
  • Developers transpile to older standards while browsers adopt new standards

Asynchronous JS

staying out of callback hell

fs.readdir(source, function (err, files) {
  if (err) {
    console.log('Error finding files: ' + err)
  } else {
    files.forEach(function (filename, fileIndex) {
      console.log(filename)
      gm(source + filename).size(function (err, values) {
        if (err) {
          console.log('Error identifying file size: ' + err)
        } else {
          console.log(filename + ' : ' + values)
          aspect = (values.width / values.height)
          widths.forEach(function (width, widthIndex) {
            height = Math.round(width / aspect)
            console.log('resizing ' + filename + 'to ' + height + 'x' + height)
            this.resize(width, height).write(dest + 'w' + width + '_' + filename, function(err) {
              if (err) console.log('Error writing file: ' + err)
            })
          }.bind(this))
        }
      })
    })
  }
})

Taken from callbackhell.com

Why is this a thing?

  • It's not as if JS is particularly well-suited to asynchronous programming
  • It's history in the browser meant that blocking on IO was a nonstarter
  • This philosophy is central to Node.js

Rightward Drift

// Getting into callback hell
$.ajax('https://my.api.com/will').done(function(userResponse) {
    let link = response.body.friends;
    $.ajax(link).done(function(friendsResponse) {
        for (let friend of friendsResponse) {
            let imgLink = friend.profilePicture;
            $.ajax(imglink).done(function(imageBlob) {
                imageBoard.push(imageBlob);
            })
        }
    })
});

Naming Functions

// Breaking out into functions

let addImageToBoard = (imageBlob) => imageBoard.push(imageBlob);

function fetchFriendImages(userResponse) {
    for (let friend of friendsResponse) {
        let imgLink = friend.profilePicture;
        $.ajax(imglink).done(addImageToBoard);
    }
}

$.ajax('https://my.api.com/will').done(function(userResponse) {
    let link = userResponse.friends;
    $.ajax(link).done(fetchFriendImages);
});

Using Promises

// Writing sequential-looking code with promises

fetch('https://my.api.com/will')
.then(userResponse => fetch(userResponse.friends))
.then(friendResponse => {
    let imgPromises = friendResponses.map(f => fetch(f.profilePicture));
    return Promise.all(imgPromises);
})
.then(images => {
    for (let img of images) {
        imageBoard.push(img);
    }
});

Data Visualization

A Library Tour

D3 is Cool, Right?

  • Yes! But not great for beginners.
  • D3 is intended to provide low-level graphing primitives - an API to create SVGs that react to your data
  • Unless you're creating a special snowflake, you probably should start by taking a look at libraries like c3, Rickshaw, Highcharts, and nvd3

Mapping

  • Leaflet is worth learning in depth
  • Blog post walking through a Chicago visualization

Learn More

Title Text

JavaScript for Data Analysts

By Will Engler

JavaScript for Data Analysts

Chapin Hall 3/29/17

  • 767