UX Camp

Web Frontend Dev

Part 2 of 4: JavaScript


Presented on 8 March 2013.


Press down for video or right for slides.

Presented by

John-Philip Johansson at Avanade

Tip: Watch in fullscreen. It's in HD.

Download: MP4 720p, MP4 480p, OGG 720p, or OGG 480p.

Win a book

Be active during the presentation :)

photo of two js books

Left: JS - The Good Parts

Right: JS - The Definitive Guide

Misunderstood


JavaScript is the world's most misunderstood programming language

Douglas Crockford

Types


  • object
  • number
  • string
  • array
  • boolean
  • function

object

Container of properties,

where properties have name and value


var example = {
  'requires-quotes': 1,
  does_not_require_quotes: 2
};

var one = example['requires-quotes'];      // called 'bracket notation'
var two = example.does_not_require_quotes; // called 'dot notation'
example.oops === undefined

number

64-bit floating point


100 === 1e2

var x = NaN;
x !== NaN // NaN always results in false
isNaN(x) === true // This is how you test for NaN

Infinity > 1.79769313486231570e+308

+'123' === 123 // convert string to number

0 == false
NaN == false
Math.floor(3.14) === 3

string

16-bit unicode


'hello' === "hello"

'hello'.length === 5
'hell' + 'o' === 'hello'

'' == false
'hi'.toUpperCase() === 'HI'

array

Not your typical array


var empty = [];
var numbers = [ 'zero', 'one', 'two', 'three', 'four',
                'five', 'six', 'seven', 'eight', 'nine' ];

empty[1] ===  undefined
numbers[1] === 'one'

empty.length === 0
numbers.length === 10

Lot's of methods on the Array object!

boolean

Almost typical...

...we'll talk about 'truthy' and 'falsy' later!


var t = true;
var f = false;

t !== f
t === !f
!t === f

function

The best thing about JavaScript...

Function Statement

function foo() {}  // beware: hoisting

Function Expression

var foo = function() {};

Object


Reference

Prototype

Object object

Reflection

Delete

JSON

Reference

Objects are always passed by reference


var foo = {};
var x = foo;
x.name = "Bar";

foo.name === x.name

Prototype


var foo = {};
typeof foo.uhoh === 'undefined'
typeof foo.toString === 'function'

Object prototype


  • create
  • constructor
  • hasOwnProperty
  • isPrototypeOf
  • propertyIsEnumerable
  • toLocaleString
  • toString
  • valueOf

Reflection

var foo = {};
foo.bar = 'hi!';
foo.hasOwnProperty('bar') === true
foo.hasOwnProperty('toString') === false

Delete


var foo = {};
foo.bar = 'hi!';
delete foo.bar;  // ok!
delete foo.uhoh; // also ok!

delete foo; // will throw in 'strict mode'

JSON

JavaScript Object Notation


Often used instead of XML


var json = '{ "result": true, "count": 1}';
var obj = JSON.parse(json);    // requires ECMAScript 5
var str = JSON.stringify(obj); // this too

If not available, use Crockfords JSON2 library.

Functions


Function objects

Function prototype

Return value

Function vs. method vs. constructor

Control 'this'

Be controlled by 'this'

Arguments

Function Objects


var foo = function () { return 'hi'; };
foo.hah = function () { 
  return function() {
    return 'omg...';
  };
};

Function prototype


  • apply
  • arguments
  • bind
  • call
  • caller
  • constructor
  • hasOwnProperty
  • isPrototypeOf
  • length
  • name
  • propertyIsEnumerable
  • prototype
  • toLocaleString
  • toString
  • valueOf

Return value

var func = function() { };
func() === undefined;

var func2 = function() { return; };
func2() === undefined;

var func3 = function() { return 0; };
func3() === 0;

Function vs. Method vs. Constructor


Function

var myFunction = function() { };

Method

var myObject = {
  myMethod: function() { }
};

Constructor

var MyClass = function() { };

Function: this


'this' is bound to the global object

var myFunction = function() { 
  this.hi = 'bang!';
};

window.hi; // 'bang!'

Method: this


'this' is bound to the owning object

var myObject = {
  hi: 'ping!',
  myMethod: function() {
    this.hi = 'pong!';
  }
};

myObject.hi; // 'ping!'
myObject.myMethod();
myObject.hi; // 'pong!'

myObject['myMethod'](); // alternative way to call

Constructor: this


'this' is bound to to the new object

var MyClass = function () {
  this.member = 'hi';
};

var myObj = new MyClass();
myObj.member === 'hi';
// Don't do this!
MyClass();
window.member === 'hi'; // Ooops!

Control this


var dog = {
  sound: 'Arrooooo',
  howl: function() { return this.sound; }
};

dog.howl() === 'Arrooooo';

Apply & Call

var brave = { sound: 'ROAAAARRRR' };
dog.howl.apply(brave) === 'ROAAAARRRR';
dog.howl.call(brave) === 'ROAAAARRRR';

Be controlled by this


function buttonClicked(){ alert(this.id); }
var button1 = document.getElementById('btn1');
var button2 = document.getElementById('btn2');

button1.onclick = buttonClicked;
button2.onclick = function() { buttonClicked(); };

Arguments


var howMany = function() {
  return arguments.length;
};

howMany('hi', 4, window) === 3;

Arguments with apply


var howMany = function() {
  return arguments.length;
};

howMany.apply(null, ['hi', 4, window]) === 3;

var callConsole = function() {
  var params = [].slice.call(arguments);
  console.log.apply(console, params);
};

howMany.apply(null, ['hi', 4, window]) === 3;

Arguments with call


var howMany = function() {
  return arguments.length;
};

howMany.call(null, 'hi', 4, window) === 3;

Scope


Function scope, not block scope

Hoisting

Closure

Scope


Block syntax !== block scope

Uses function scope

var foo = function(bar) {
  if (bar === 'baz') {
    var hi = 'hello';
  } else {
    var hi = 'uhoh';
  }

  return hi;
};

Hoisting


var foo = function(bar) {
  var hi;

  if (bar === 'baz') {
    hi = 'hello';
  } else {
    hi = 'uhoh';
  }

  return hi;
};

More hoisting


bar();

function bar() {
  console.log('hi');
};

var bar;

bar();

bar = function() {
  console.log('hi');
};

Closure


Inner scopes access outer scopes


var secret = 'sssh';

document.getElementById('myDiv').onclick = function() {
  this.innerHTML = secret; // the cat's out of the bag!
};

Inheritance


Pseudoclassical

Prototypal

Functional

Parts

Pseudoclassical


var Mammal = function(name) {
  this.name = name;
};
Mammal.prototype.get_name = function() {
  return this.name;
};

var Cat = function(name) {
  this.name = name;
};
Cat.prototype = new Mammal();
Cat.prototype.purr = function() { };

Prototypal


var myMammal = {
  name: 'Henry',
  get_name: function() {
	return this.name;
  };
};

var myCat = Object.create(myMammal);
myCat.name = 'Sonic';
myCat.purr = function() { };
Differential inheritance

Functional


var mammal = function(species) {
  var that = {}; // will be the instance

  that.get_name = function() {
    return species.name;
  };

  return that;
};

var cat = function(species) {
  var that = mammal(species);

  that.purr = function() { };

  return that;
};

Parts


var mammal = function(subSpecies, name) {
  subSpecies.get_name = function() {
    return name;
  };

  return subSpecies;
};

var cat = {};
cat = mammal(cat, 'Sonic');

JavaScript Structure


// space in functions and comments above
foo( arg );

// all other times use ===
undefinedOrNull == null;

// jQuery objects are prefixed with $
var $elements = $('div');

Lint your code with JSLint or JSHint

jQuery's JavaScript Style Guide

Library: jQuery


jQuery is not JavaScript, it's just a library!


Read the API docs for fun!

Selectors

Cross-browser element selection


Borrows syntax from CSS

var $myElement = $('.myClass');
$myElement = $('#myId');
$myElement = $('div');

$myElement = $('input[type="checkbox"]:checked');

DOM Manipulation


$myElement.addClass('highlight');
$myElement.hasClass('highlight') === true

$myElement.attr('style', 'background: red');
$myElement.css('background: red');

$myElement.prepend('<h1>Oh hi!</h1>');

Events


$myElement.click(myClickHandler);
$myElement.bind('click', myClickHandler);
$myElement.live('click', myClickHandler);
$myElement.on('click', myClickHandler);
$myElement.one('click', myClickHandler);
$(document).ready(function() { /* document ready */ });
$(function() { /* same thing */ });

Effects


$myElement.fadeIn('fast');
$myElement.fadeOut('slow');

$myElement.slideDown();
$myElement.slideUp();

More effects available in jQuery UI.

AJAX


jQuery.get('/api/dogs/1').done(someFunc);
jQuery.getJSON('/api/dogs/1').done(someFunc);

jQuery.post('/api/dogs', theData).done(someFunc);

Library: Knockout


MVVM library

MVVM pattern

Model View View-Model


Originated from Microsoft, for WPF


Based on MVC (Model View Controller)


Separate the GUI from the back-end

Demo


The best library intro ever.

Library: Modernizr


Check for HTML5 features and act accordingly

Load polyfills

polyfills: a JS shim that replicates standard API for older browsers


Modernizr.load({
  test: Modernizr.geolocation,
  yep : 'geo.js',
  nope: 'geo-polyfill.js'
});

Style if supported


<html class="js no-touch postmessage history boxshadow ...">
  <head></head>
  <body>
    <div class="box"></div>
  </body>
</html>
.box {
   border-bottom: 1px solid #666;
   border-right: 1px solid #777;
}

.boxshadow .box {
   border: none;
   -webkit-box-shadow: #666 1px 1px 1px;
      -moz-box-shadow: #666 1px 1px 1px;
           box-shadow: #666 1px 1px 1px;
}

Pitfalls


Don't try this at home!

with


with (obj) {
  a = b;
}

Means any of these

a = b;
a = obj.b;
obj.a = b;
obj.a = obj.b;

eval

Pronounced 'evil'


eval('var sum = 1 + 4;');

Bitwise operators


&  and
|  or
^  xor
~  not

Remember, JS doesn't have integers!

Typed Wrappers


new Boolean(true)  // true
new Number(4)      // 4
new String('abc')  // 'abc'
new Object()       // {}
new Array()        // []

new


Remember, functions and constructors are similar

var Thing = function() { this.hello = 'world'; };

var yes = new Thing(); // attaches 'hello' to 'a'
var doh = Thing(); // attaches 'hello' to the global object

Capitilize constructors if you use them

void


It's an operator...

void 123 === undefined

More Pitfalls

Seriously, don't try this at home!

Global Variables


var hi = 'hello';
window.hi = 'hello';
hi = 'hello'; // called 'implied global'

Semicolon insertion


JS will try to add ; where needed

do not rely on it!

return // ; inserted here!
{
  status: true
};

Reserved words


abstract boolean break byte case catch char class const continue debugger
default delete do double else enum export extends false final finally
float for function goto if implements import in instanceof int interface
long native new null package private protected public return short static
super switch synchronized this throw throws transient true try typeof var
volatile void while with

Can still be used with bracket notiation

foo['boolean']; // ok
foo.boolean; // not ok!

typeof


typeof null === 'object'

parseInt()


Usually starting with 0 indicates base 8

parseInt('09') === 0 // not always, could be 9
parseInt('09', 10) === 9 // always supply the radix

NaN and Infinity

(NaN = Not a Number)


typeof NaN === 'number'
NaN === NaN // false!
NaN !== NaN // true!

isNaN(NaN) === true
isNaN(Infinity) === false

isFinite(NaN) === false
isFinite(Infinity) === false
isFinite(123) === true

Phony Arrays


typeof [] === 'object'

[].constructor === Array // true! sometimes...

Array.isArray([]) === true  // ECMAScript 5
$.isArray([]) === true      // jQuery

Falsy Values


These count as 'falsy'

0
NaN
''
null
false
undefined
if (!myValue)
  // myValue is one of the above

!!myValue // turns it into boolean

Falsy and boolean operators


console.log && console.log('hi'); // prints 'hi' if console.log exists

return myValue || myDefault; // 'myValue' if truthy, else 'myDefault'
return (typeof other === 'object' && other) || that; // too cute
return typeof other === 'object' ? other : that; // preferable

Equality


1 == '1'  // allows type coercion
1 === parseInt('1') // checks type as well

null == undefined
'' == 0

for in


for (part in myCar) { // no guarantee on order
  if (myCar.hasOwnProperty(part))
    // do stuff
}

// or with jQuery:
$.each(myCar, function(part) { 
  // do stuff
});

Implicit coercions


isNaN('foo') === true
isNaN(undefined) === true
isNaN({}) === true
isNaN({valueOf: 'foo'}) === true
x !== x // only true if NaN

truthy and falsy


function point(x, y) {
  if (!x)
    x = 320;
  if (!y)
    y = 240;

  return { x: x, y: y };
}

point(0, 0) === { x: 320, y: 240 };
function point(x, y) {
  if (typeof x === "undefined")
    x = 320;
  if (typeof y === "undefined")
    y = 240;

  return { x: x, y: y };
}

point(0, 0) === { x: 320, y: 240 };

Promise


Read the book JavaScript - The Good Parts

before touching JS code again.


Please? :)

Resources


Some videos,

a few articles,

and lots of free libraries

JavaScript, wat?

Hilarious 4min presentation of quirkiness!


View it here.

Good JavaScript Habits for C# Developers


Source

Knockout JS: Helping you build dynamic JavaScript UIs with MVVM and ASP.NET


Source

Writing Maintainable JavaScript


Source

Articles


Everything written by Douglas Crockford

Writing Fast, Memory-Efficient JavaScript

Useful JavaScript Libraries and jQuery Plugins - Part 1

Useful JavaScript Libraries and jQuery Plugins - Part 2

JavaScript Events And Responding To The User

Managing JavaScript on Responsive Websites

Which JavaScript framework (jQuery vs Dojo vs … )?

Plain Old JavaScript

More articles


Debugging JavaScript with Chrome

CoffeeScript or Straight Up Javascript? It's Decision Time

A re-introduction to JavaScript (JS Tutorial)

The rise and rise of JavaScript

Ten Oddities And Secrets About JavaScript

Javascript on the server side

Unobtrusive JavaScript (Wikipedia)

JavaScript utility libraries


JavaScript other libraries


the End?


Questions?



Next Friday we'll talk best practices!


bit.ly/webfrontend