JavaScript for the
Java Developer

TJ VanToll
March 20th, 2012

Me

You should probably feel really sorry for them.

JavaScript - A Real Brief History

1990 - First successful HTTP communication

1993 - Mosaic adds images to the internet.

Early Internet

JavaScript's Begininngs

History Continued

ECMAScript was always an unwanted trade name that sounds like a skin disease.
Brendan Eich

ECMAScript Editions

Pretty much the only thing Java and JavaScript share is C style styntax.

//JavaScript        		
for (var i = 0; i < foo.length; i++) {
    if (bar) {
        doSomething();
    } else {
        doSomethingElse();
    }
}
        		
//Java        		
for (int i = 0; i < foo.length; i++) {
    if (bar) {
        doSomething();
    } else {
        doSomethingElse();
    }
}
        		

Typing

Java is strongly typed.

      		
Integer foo = 8; String bar = "hello";
        		

JavaScript is loosely typed.

      		
var foo = 8, var bar = 'hello', foo = bar = {};
        		

JavaScript variable types

Special types of Objects

JavaScript uses type coercion whenever it needs to perform an operation on two operands that need to be the same type and are not.

8 == "8" //true
				

Relying on type coercion is not a good idea.

null == undefined  //true
false == undefined //false
false == "false"   //false				

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

Type Coercion

To avoid type coercion use the === and !== operators.

8 === "8"           //false				
				
null === undefined  //false
false === undefined //false
false === "false"   //false				

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

Number

Numbers in JavaScript are "double-precision 64-bit format IEEE 754 values".

0.1 + 0.2 == 0.3; //false				
				

You can use parseInt to convert Strings to "Integers"

parseInt("20", 10); //20				
				

A special value, NaN ("Not a Number") is returned if the string is non-numeric.

parseInt("ABC", 10) //NaN
				

JavaScript Quiz

1 / 0

Infinity

Quiz Part 2

-1 / 0

-Infinity

Strings

JavaScript has no character type.

Methods

'bar'.replace('a', 'b'); //'bbr'
'bar'.split('a'); //['b', 'r']				
				

Objects

JavaScript objects are simply collections of name value pairs.

//JavaScript
var foo = {};
foo.bar = 'hi';
console.log(foo.bar); //"hi"
console.log(foo['bar']); //"hi"
				
//Java
Map<String, Object> foo = new HashMap<String, Object>();
foo.put("bar", "hi");
System.out.println(foo.get("bar")); //"hi"
				

Objects Continued

You can retrieve members of the object using dot or bracket notation.

var dog = {
    name: 'Rover',
    bark: function() { return 'woof'; }
};				

dog.name; //'Rover'
dog['name']; //'Rover'
dog.bark();  //'woof'
dog['bark'](); //'woof'
				

Iterating over Object Members

You can iterate over JavaScript Objects using for in loops.

var dog = {
    name: 'Rover',
    noise: 'bark'
};				
for (var prop in dog) {
    console.log("Property: ", prop);
    console.log("Value", dog[prop]);
}

//Logs: 
//Property: name
//Value: Rover
//Property: noise
//Value: bark
				

Functions

Functions are first class citizens in JavaScript.

Meaning, you can store them in variables...

var foo = function() {};				
				

…pass them around as parameters, etc...

setInterval(foo, 2000);				
				

Parameters

function doSomeMath(x, y) {
    return x + y / 6 + x;
};				
				

Even though you define the number of arguments a function takes, you can pass as many as you'd like. All arguments are made available through an arguments array-like property.

Default Argument Values

Currently

function addIt(bar) {
    bar = bar || 8;
    return bar + 2;
};
				

ECMAScript 6 Proposed

function addIt(bar = 8) {
    return bar + 2;
};				
				

this

In JavaScript you can change the invocation context for a function, i.e. you can literally change the value of this when you invoke a function.

window.name = 'bar';
var foo = function() {
    console.log(this.name);
};
	
foo(); //'bar'
foo.apply( { name: 'lalala' } ); //'lalala
				

How is this useful?

jQuery Event Handlers

$('button').on('click', function() {
    //this is set to the button that was clicked on.
});				
				

Namespacing

Java has Packages

Java Packages

The folder structure must match the package structure.

Namespacing in JavaScript

There is no native namespacing mechanism in JavaScript. The only built in way for scripts to communicate is via the global object.

A number of namespacing patterns are used to provide Java-like functionality.

Using Objects to Provide Namespaces

myApp = {};
myApp.builder = {
    init: function(){},
    destroy: function(){}
};

Continued nesting:

myApp = myApp || {};
myApp.pages = myApp.pages || {};
myApp.pages.signup = {
    load: function(){}
};

jQuery's $.extend

var myApp = myApp || {};
​$.ext​end(​myApp, {
    builder: {},
    init: {},
    unload: {}     
});​​

Dojo

Define your base level namespace.

<script>
dojoConfig = {
    paths: {
        'myNamespace': '/path/to/myNamespace'
    }
};
myNamespace = {};
</script>
<script src="//ajax.googleapis.com/ajax/libs/dojo/1.7.2/dojo/dojo.js"></script>
				

dojo.require

File at /myNamespace named foo.js

dojo.provide("myNamespace.foo");
myNamespace.foo = function() {};
				

Then to get that file asynchronously and added to the main namespace.

dojo.require("myNamespace.foo");				
				

Visibility / Scoping

Visibility in Java

Visibility in JavaScript

Everything is based on functions.

var s = 1;
var t = function() {
    var u = 2;
    var v = function() {
        var w = 3;
    }; 
};
var x = function() {};
				

Design Patterns

Module Pattern

var Foo = function() {
    var bar = {};

    this.getBar = function() {
        return bar;
    };
	
    this.setBar = function(bar) {
        this.bar = bar;
    }
};

var foo = new Foo();
foo.setBar('hi');
foo.getBar('hi');
foo.bar; //Error
				

Module Pattern Issues

Calling public methods from private ones is awkward.

var Foo = function() {
    var init = function() {
    	this.stuff();  //JS Error
    };

    this.stuff = function() {
    	return 'stuff';
    };
    
    init();
};
				

Modern Pattern Fix

var Foo = function() {
    var that = this;
    
    var init = function() {
    	that.stuff();
    };

    this.stuff = function() {
    	return 'stuff';
    };
    
    init();
};
				

Revealing Module Pattern

var Foo = function() {
    var init = function() {
    	stuff();
    };

    var stuff = function() {
    	return 'stuff';
    };
    
    init();
    
    return { stuff: stuff };
};
				

Modules in ES6

module Foo {
    var init = function() {
        stuff();
    };
    
    export function stuff() {
        return 'stuff';
    };
};
				

Dealing with Global Variables

Both of these are global variables.

var foo = 'foo';
var bar = function() {};
				

Wrap this with a function and they're no longer global.

function wrapper() {
    var foo = 'foo';
    var bar = function() {};
};					
					

IIFE (Immediately Invoked Function Expression)

An elegant way of mimicking block scoping in JS.

(function() {
    var foo = 'foo';
    var bar = function() {};
}());				
				

See jQuery

Classes and Inheritance

Classes in Java

In Java, other than a few primitives everything is an Object and an Object of some Class.

public class Poodle {
    private String name;
    
    public String getName() {
        return name;
    }
    
    public void setName(String name) {
        this.name = name;
    }
}				
				

Classes in JavaScript

There are no native classes in JavaScript.

Classes are unlikely to be added because the standards committee doesn't want to offer two different inheritance models in the same language.

There is still a chance for class syntax that is simply syntax sugar for valid ES5 JavaScript.

Inheritance in Java

Java has classical single inheritance, every class extends Object.

public class Poodle extends Dog {
    private String name;
    
    public String getName() {
        return name;
    }
    
    public void setName(String name) {
        this.name = name;
    }
}				
				

Warning: Average Java programmer's first experience with prototype inheritance

Inheritance in JavaScript

JavaScript uses single prototype inheritance. All objects have a prototype.

A prototype is simply an Object.

Inheritance in JavaScript

Much like all classes in Java have Object at the end of their inheritance chain, all Objects in JavaScript have Object.prototype at the end of their prototype chain.

For example, the valueOf function is defined in Object.prototype, so it can be called on essentially anything in JavaScript.

new String().valueOf();
new Number().valueOf();
new Boolean().valueOf();
new Function().valueOf();
new Object().valueOf();
new Array().valueOf();
				

Core Prototypes

The following are examples of some of the prototypes built into the language. You can type these into a JavaScript console with autocomplete (Firebug or WebKit Web Inspector) and see what are in the following.

Basic Example - Java

public class Animal {
    public String eats() {
        return "meat";
    }

    public String noise() {
        return "roar";
    }
}

public class Dog extends Animal {
    public String noise() {
        return "bark";
    }
}

new Dog().eats(); //"meat"
new Dog().noise(); //"bark"
				

JavaScript Equivalent

var Animal = function() {};
Animal.prototype.eats = function() {
    return 'meat';
};
Animal.prototype.noise = function() {
    return 'noise';
};

var Dog = function(){};
Dog.prototype = new Animal();
Dog.prototype.noise = function() {
    return 'bark';
};

new Dog().eats(); //"meat"
new Dog().noise(); //"bark"
				

Viewing the Prototype

Functions have a prototype property set to their prototype Object. The only way to view the prototype of an Object before ES5 was to look at the non-standard __proto__ property.

In ES5 you can use Object.getPrototypeOf().

var x = function() {};
x.prototype;

var y = {};
Object.getPrototypeOf(y);
				

Adding to Built in Prototypes

You can add methods to the built in prototypes.

For example, IE < 9 doesn't have a trim method in String.prototype, but thanks to JavaScript's dynamic nature you can make one.

if (!String.prototype.trim) {
    String.prototype.trim = function(value) {
        //implement a trim here
    }
}
				

As an example of this feature detection see the trim method in jQuery. However, jQuery doesn't add to the prototype.

Built in Prototypes

You can even change the behavior of core methods.

String.prototype.trim = function() {
    //Whatever you'd like.
};				
				

Can be handy for unit testing.

Dangers of Adding to the Built in Prototypes

Until ES5 there was no way of adding to Object.prototype without the property being enumerable in a for in loop.

Object.prototype.foo = function() {};

var anObject = {
    a: 1,
    b: 2,
    c: 3
};

for (var prop in anObject) {
    console.log(prop + " = " + anObject[prop]);
}				

//Logs:
//a = 1
//b = 2
//c = 3
//foo = function() {}
				

Fix for enumeration in ES3

This can be fixed by wrapping everything within the loop in a Object.hasOwnProperty check:

Object.prototype.foo = function() {};

var anObject = {
    a: 1,
    b: 2,
    c: 3
};

for (var prop in anObject) {
    if (anObject.hasOwnProperty(prop)) {
        console.log(prop + " = " + anObject[prop]);
    }
}				
				

Fix for enumeration in ES5

Object.defineProperty(Object.prototype, 'foo', { 
    value: function(){},
    enumerable: false
});

var anObject = {
    a: 1,
    b: 2,
    c: 3
};

for (var prop in anObject) {
    console.log(prop + " = " + anObject[prop]);
}				
				

Adding to Prototypes in JS Libraries

Whether or not the native prototypes are added to is a dividing line amongst popular libraries.

Libraries that do:

Libraries that do not:

Other Class Options in JS

Plenty of people prefer classical inheritance and sought to replicate it in JS.

MooTools Classes

var Animal = new Class({
    noise: function() {
        console.log('roar');      
    }
});

var Dog = new Class({
    Extends: Animal,
    noise: function() {
        console.log('bark');               
    }       
});

new Animal().noise(); //'roar'
new Dog().noise(); //'bark'	
				

Dojo Classes

require(['dojo/_base/declare'], function(declare) {
    declare("Animal", null, {
        noise: function() {
            console.log('roar');
        }           
    });
	
    declare("Dog", Animal, {
        noise: function() {
            console.log('bark');
        }           
    });
});
		
new Animal().noise(); //'roar'
new Dog().noise(); //'bark'	
				

JavaScript's Bad Parts

JavaScript's Rough Parts

There are a lot of them. Here is a small sampling, for a more comprehensive list check out Douglas Crockford's JavaScript the Good Parts.

Global Variables

var foo = function() {
    for (x = 0; x < something.length; x++) {
        console.log(something[x]);
    }
};

function bar() {
    //whatever
}

//x and bar are now global variables
				

Block Scoping

There is none.

{
    var x = 2;
}
console.log(x); //2

for (var y = 0; y < 8; y++) {}
console.log(y); //8	
				

Octal Numbers

Numbers with leading zeros are treated as octal numbers in JavaScript.

010 === 8 //true				
				

This is handled the same in Java. The difference is how Strings are converted into integers.

//Java
Integer.parseInt("010"); //10				
				
//JavaScript
parseInt("010"); //8
parseInt("010", 10); //10				
				

Why isn't this stuff fixed?

ECMAScript 5 Strict Mode

ECMAScript 5 introduced strict mode, a way of opting in to a restricted variant of JS.

var foo = function() {
    "use strict";
    x = 2; //error
};
foo();
				

Support

ECMAScript 6

ECMAScript 6 contains some proposed major changes to the language. Features under discussion:

ECMAScript 6's let keyword

The let keyword can be used to offer true block scoping.

for (var x = 0; x < 8; x++) {}
console.log(x); //8

for (let y = 0; y < 8; y++) {}
console.log(y); //ReferenceError
				

JavaScript as a Compile Target

Languages

Most all languages have had something written to compile them into JavaScript. There's a giant list at https://github.com/jashkenas/coffee-script/wiki/List-of-languages-that-compile-to-JS

CoffeeScript

CoffeeScript

CoffeeScript Example - Functions

//CoffeeScript
double = (num) -> num * 2		
				
//JavaScript
var double = function(num) {
    return num * 2;
};				
				

CoffeeScript Example - if else blocks

//CoffeeScript				
if happy and knowsIt
    clapsHands()
else
    doSomethingElse()				
				
//JavaScript				
if (happy && knowsIt) {
    clapsHands();
} else {
    doSomethingElse();
}				
				

CoffeeScript Example - Switch Statements

//CoffeeScript
switch day
    when "Fri", "Sat"
        if day is sunny
            go outside
    when "Sun" then go mall
    else go work				
				
//JavaScript
switch (day) {
    case "Fri":
    case "Sat":
        if (day === sunny) go(outside);
        break;
    case "Sun":
        go(mall);
        break;
    default:
        go(work);
}				
				

Dart

Dart

Dart

You can try writing some Dart at http://try.dartlang.org.

Criticism

"JavaScript is already there. On a couple of billion devices… If you want to work with the web, learn JavaScript. If you don’t want to learn JavaScript, stay the hell away from the web."

Back to JavaScript… and about time to end this.

Reasons JavaScript has become way more awesome in the last few years, and why you might want to give it another shot.

The End

Thanks