JavaScript all the things meme

Why JavaScript?

Ubiqutous

Quirky

Fun!

A humane programming language (it has flaws)

Where can we use JavaScript?

Browser logos
NodeJS logo
Raspberry Pi
Arduino Uno
Leap Motion
PostgreSQL database logo
Any application that can be written in JavaScript, will eventually be written in JavaScript.
Atwood's Law
Jeff Atwood, Stack Exchange (stackoverflow.com)

Today's agenda

Something boring

Something necessary

Something interesting

Something awesome

Something surprising

Something bad

Today's agenda in detail

Boring: A brief history of JavaScript

Necessary: The type system

Interesting: Truthiness, Prototypal inheritance

Awesome: First class functions, Object literals, Closures

Surprising: Scoping, Concurrency

Bad: Global variables, Equals, and more

A brief history of JavaScript

(actually not that boring)

In the beginning...

In 1995, Netscape Navigator was the dominant web browser, but Microsoft was making inroads with Windows 95.

Netscape considered the web browser a new form of distributed OS, but it needed a lightweight scripting language.

They hired Brendan Eich in April 1995 and told him he had ten days to design a programming language.

Brendan created Mocha, later renamed to LiveScript, borrowing ideas from LISP, Smalltalk, Self and C.

Netscape Navigator 2.0 Beta was released in September 1995.

So why is it called JavaScript?

Java had just been released and was getting a lot of attention.

Netscape marketing changed the name from LiveScript to JavaScript in December 1995.

Netscape Navigator 2.0 with JavaScript support launched in March 1996.

Netscape delivered JavaScript to Ecma International for standardisation.

June 1997: First edition of ECMA-262 ECMAScript Language Specification.

Today in the browser: es5

Today on the server: es6

Tomorrow: es7

The type system

(it's quite simple)

Types

Number

String

Boolean (true and false)

Null (null)

Undefined (undefined)

Object (a few types)

Number usage

var aNumber = 1;
var anotherNumber = 0.1;
1 / 0;
>> Infinity
Math.sqrt(-1);
>> NaN  // not a number
0.1 + 0.2;
>> 0.30000000000000004

JavaScript uses binary floating point arithmetic (IEEE 754).

String usage

var empty = '';
var helloWorld = 'Hello World!';
var escaping = 'It\'s a glorious day!';
'abc' + 'def';
>> 'abcdef'
1 + '2';
>> '12'

JavaScript does some type coercion (Number to String here).

Objects

Arrays

Functions (more on this later!)

Regular expressions

Objects (duh!)

More on objects

Containers of properties that are name/value pairs

Names can be any String

Values can be any expression

Mutable

Strings and Numbers are not objects (they are object-like but immutable)

Object usage

Simple:

var empty = {};
var simple = { 'name': 'value', 'name2': 'value2' };

Mutate:

simple['another name'] = 'another value';

Query:

simple['name'];  // or simple.name;
>> 'value'

Arrays

Simple:

var empty = [];
var numbers = [ 'zero', 'one' ];

Mutate:

numbers.push('two');   // [ 'zero', 'one', 'two' ]
numbers[0] = 'zilch';  // [ 'zilch', 'one', 'two' ]

Query:

numbers[1];
>> 'one'
numbers.length;
>> 3

Interesting parts

Truthiness, prototypal inheritance

Truthy and falsy

All expressions are either truthy or falsy.

This can be used in conditional expressions:

if (someVariable) {
    console.log("this only executes if someVariable is truthy");
}

Can be used as a simple check for null, undefined, NaN and more.

Falsy values

Value Type
0 (zero) Number
NaN (not a number) Number
'' (empty string) String
false Boolean
null Object
undefined Undefined

Prototypal inheritance

A new object can inherit properties of an existing object.

Example: Arrays inherit properties of the Array prototype object, such as length

Another example:

var parent = {
    'name': "Alice",
    'greet': function() {
        console.log("Hello " + this.name);
    }
};
var child = Object.create(parent);
child['name'] = "Bob";
child.greet();  // prints "Hello Bob" to the console

Awesome parts

First class functions, Object literals, Closures

More on functions

Functions are objects and can be assigned to variables.

var simpleFunction = function() {
    console.log("Hello World");
};

This code doesn't print "Hello World" to the console, it only defines the function.

We can also pass functions as arguments to other functions.

And a function can return a function as output.

simpleFunction();  // prints "Hello World" to the console

Functions as return types

function createFunction() {
    return function() {
        console.log("Hello World");
    }
}

Functions as arguments

var map = function(map_function, numbers_array) {
    var result = [];
    for (var i = 0; i < numbers_array.length; i++) {
        result.push(map_function(numbers_array[i]));
    };
    return result;
};

Usage:

var square = function(num) {
    return num * num;
}
map(square, [1, 2]);
>> [1, 4]

Object literals

var myArray = [1, 2, 3];

var person = {
    "firstName": "John",
    "lastName":  "Smith",
};

var nestedExample = {
    "firstName": "Jane",
    "lastName":  "Smith",
    "address": {
        "country": "Australia",
        "city":    "Sydney"
    },
    "greeting": function() {
        console.log("Hello World!");
    }
}

Closures

Inner functions can access variables of the functions they are defined within.

var outer = function() {
    var outerVar = 'hello';

    return {
        inner: function() {
            console.log(outerVar);
        }
    };
};
// outerVar is no longer in scope

outer().inner();
>> 'hello'

Function closures as pseudo-classes

var counter = function() {
    var value = 0;

    return {
        getValue: function() {
            return value;
        },
        increment: function() {
            value += 1;
        }
    };
}

var myCounter = counter();  // create an instance

Encapsulation: value can't be directly manipulated.

Currying

Create a new function by supplying some arguments of an another function.

function describe(adjective) {
  return function(thing) {
    console.log(thing + " is " + adjective);
  }
}

var isAwesome = describe("awesome");
var isEvenBetter = describe("even better");

isAwesome("Melbourne");
isEvenBetter("Sydney");

Surprising parts

Scoping, Concurrency

Scoping

JavaScript uses C's block syntax (curly braces {}), but there's no block scope.

There are only two scopes: global scope and function scope.

A variable defined without var is global. Never do this!

A variable defined outside any function is global.

A variable defined in a function only exists in that function.

Java vs JavaScript

void mymethod() {
    if (condition == true) {
        String mystring = "hello";
    }
    // mystring is no longer in scope
}
var myfunc = function () {
    if (condition === true) {
        var mystring = "hello";
    }
    // mystring = "hello"
}
// mystring is no longer in scope

Scoping test

var first = 0;
var scopeTest = function() {
  var first = 1;
  console.log("first=" + first);
  if (true) {
      var second = 2;
  }
  console.log("second=" + second);
};
scopeTest();
console.log("first=" + first);
console.log("second=" + second);
>> first=1
   second=2
   first=0
   ReferenceError: second is not defined

Concurrency: the event loop

while (queue.waitForEventMessage()) {
  queue.processNextEventMessage();
}

Each event message is processed completely before any other message is processed.

No multi-threading support, as in C, Java, others.

How are event messages added to the queue?

  • In a browser: When a user interface event happens and an event listener is is attached.
  • Elsewhere: setTimeout() and friends

Event loop test

setTimeout(callbackFunction, delayMillis)

Adds callbackFunction as a message to the event queue, with a delay.

var counter = function() {
    for (var i = 1; i <= 3; i++) {
        setTimeout(function() { console.log(i); }, 0);
    }
}
counter();

Solution:

>> 4
   4
   4

Bad parts

Global variables, Equals, and more

Global variables

It's far too easy to create global variables!

var myFunction = function() {
    global1 = 1;
    var nonGlobal = "I only exist inside myFunction";
}
var global2 = 2;
window.global3 = 3;

global1 is global because we forgot var

global2 is global because we declared it outside of a function or object

global3 is global because we added it to the global web browser window object

Equals

JavaScript has both == and === (as well as != and !==)

== performs type coercion when the arguments are not of the same type, using strange rules:

0 == ''            // true
'0' == ''          // true
'' == '0'          // false

false == '0'       // true
null == undefined  // true

' \t\r\n ' == 0    // true

Lesson: Use === and !==

Where do I start?

JavaScript: The Good Parts book cover
Mozilla Developer Network: JavaScript
NodeJS logo

Thank you!

References