Tuesday, May 15, 2012

Introduction to JavaScript



This is the content for a presentation on JavaScript. I just made the content publicly available for interested people who attended the session. Most of the slides are very informative though so that anyone could make use of hopefully.

I'll be visiting the content and adding more clarification soon.

The Name: JavaScript

  • Prefix: Java

    Is it related to Java? A subset maybe?

    No

    It has nothing to do with Java

  • Suffix: Script

    Is it just a scripting language?

    Not a real programming language?

    No

    It is a complete programming language

Popularity

  • Available in all browsers

  • The most popular programming language

The Most Misunderstood Programming Language

  • The name

    prefix and suffix

  • It is different

    Programmers don't even bother to learn it

  • Unfairly blamed for the awfulness of the DOM

  • Previous bad implementations

  • Lack of good books

Design: Very Good Ideas

  • Functions are first class objects

    They can be passed as arguments and return values

  • Loose Typing

    Easier - more expressive

  • Dynamic Objects

    General containers = hash tables

  • Object Literal Notation

    Very expressive

Design: Controversial Ideas

  • Prototypal Inheritance

    • No Classes

    • Objects inherit directly form other objects

    • Very powerful

    • Not commonly understood very well

Design: Very Bad Ideas

  • Linkage through global variables

    • Compilation units (scipt tags) are combined in a commmon global namespace

    • Variables can collide

Types (Values)

  • Simple types

    • Numbers

    • Strings

    • Booleans

    • null

    • undefined

  • Objects

Numbers

  • Only one number type

  • 64-bit floating point (same as Java's double)

    0.1 + 0.2      // 0.30000000000000004
  • 100, 100.0, 1e2 are equivalent

  • NaN and Infinity are special numbers

Numbers: NaN

  • Special Number: Not a Number

  • Result of erroneous operations

    2 * 'a'       // NaN
  • Toxic

    5 + NaN       // NaN
  • Not equal to any value (including itself)

    NaN == NaN       // false
    isNaN(NaN)       // true

Numbers: Infinity

  • Special Number

    1 / 0           // Infinity
    1 / Infinity    // 0
  • Represents numbers > 1.79769313486231570e+308

    1.8e308       // Infinity

Numbers: Number function

  • Converts a value into a number

    Number('')          // 0
    Number('0032')      // 32
    Number('123abc')    // NaN
    Number('abc')       // NaN
  • So does the '+' prefix operator

    +''                // 0
    +'0032'            // 32
    +'123abc'          // NaN
    +'abc'             // NaN

Numbers: parseInt

  • Also converts a value into a number

  • Stops at first non-digit character

    parseInt('123abc', 10)     // 123
  • If no radix is passed it defaults to 10 (8 if input starts with 0)

    parseInt('32')         // 32   (as decimal)
    parseInt('0032')       // 26   (as octal if starts with 0)
    
  • Always specify the radix

    parseInt('0032', 10)   // 32
    parseInt('0032', 8)    // 26
    

Numbers: Math

  • An object containing methods that act on numbers

    abs, acos, asin, atan, atan2, ceil, cos, exp, floor, log, max, min, pow, random, round, sin, sqrt, tan

    Math.floor(12.53)          // 12
  • Also contains some useful constants

    E, LN10, LN2, LOG10E, LOG2E, PI, SQRT1_2, SQRT2

    Math.PI                   // 3.141592653589793

Strings

  • 0 or more 16-bit characters

  • A character is just a String of length 1

  • Immutable

  • String literal

    'abc' == "abc"    // true
  • length property (number of 16-bit characters)

    'abc'.length      // 3

Strings

  • Concatenating

    'Java' + 'Script'     // 'JavaScript'
  • String function

    String(123)           // '123'
  • Strings have methods

    'cat'.toUpperCase()   // 'CAT'

Boolean

  • true - false

  • Boolean function

    Boolean(truthy_value)    // true
  • !! prefex operator

    !! falsy_value          // false

null

  • A value that is not anything

undefined

  • A value that is not even a value

  • The default value for variables and parameters

  • The value of missing members of an object

Falsy values

  • 6 possible falsy values

    !! false         // false
    !! null          // false
    !! undefined     // false
    !! ''            // false
    !! 0             // false
    !! NaN           // false
  • All other values are truthy

    !! '0'          // true

Objects

  • An object is a container of properties

  • A property has a name (string) and value (any type)

  • Class-free (No constraints on names/values of new properties)

  • Objects are hash tables

  • Protype linkage

  • Arrays, functions, regular expressions and objects are objects

Objects: Object literal

  • Very convenient for creating new object values

  • A pair of curly braces surrounding 0+ name/value pairs

    var empty_object = {};
    var person = { 'first-name': 'John' };
    var city = {
      name: 'Alexandria',
      location: { latitude: 31.2, longitude: 29.9 }
    };

Objects: Retrieval

  • Subscript notation

    person['first-name']    // 'John'
    city['name']            // 'Alexandria'
  • Dot notation

    city.name               // 'Alexandria'
    city.location.latitude  // 31.2
  • Missing properties

    person.nickname        // undefined

Objects: Retrieval

  • || operator (set default values)

    var name = person.nickname || 'anonymous';    // 'anonymous'
  • && operator (handle missing nested objects)

    city.country                       // undefined 
    city.country.name                  // throws a TypeError
    city.country && city.country.name  // undefined

Objects: Update

  • Simply by assignment

    person['first-name'] = 'Thomas';    // Replaced 'first-name'
    person['last-name'] = 'Anderson';   // Added 'last-name'

Objects: Reference

  • Objects are passed around by reference

    var x = person;    // x & person refer to the same object
    x.nickname = 'Neo';
    
    person.nickname    // 'Neo'
    
    var a = {}, b = {}, c = {};      // different empty objects
    var a = b = c = {};              // the same empty object

Objects: Prototype

  • Every object is linked to a prototype object

  • Objects created by object literal are linked to Object.prototype

    Object.prototype.foo = 'bar';
    var a = {}, b = {};
    a.foo      // 'bar'
    b.foo      // 'bar'
    
  • Protype link is used only for retrieval (prototype chain)

    a.foo = 'blah';  // Added foo property to a
    a.foo            // 'blah'
    b.foo            // 'bar'
    

Objects: Prototype

  • We can specify the prototype for a new object

  • Complex but simplified by Object.create function (in new JS editions)

    if (typeof Object.create != 'function') {
      Object.create = function(o) {
        var F = function F(){};
        F.prototype = o;
        return new F();
      };
    }
    
    var p = {foo: 'bar'};
    
    var a = Object.create(p);
    
    a.foo          // 'bar'
    

Objects: Reflection

  • hasOwnProperty

    Object.prototype.foo = 'bar';
    var a = {foo: 'blah'}, b = {};
    a.foo      // 'blah'
    b.foo      // 'bar'
    
    a.hasOwnProperty('foo')    // true
    b.hasOwnProperty('foo')    // false
    

Objects: Enumeration

  • for in

    var someone = {'first-name': 'John', 'last-name': 'Doe'};
    
    var person = Object.create(someone);
    person.profession = 'artist';
    person.age = 30;
    
    for (p in person) {
      var mark = person.hasOwnProperty(p) ? '  ' : '* '
      console.log(mark + p + ': ' + person[p]);
    }
    //   profession: artist
    //   age: 30
    // * first-name: John
    // * last-name: Doe

Objects: Delete

  • delete removes a property from an object

    delete person.age;
    person.age                       // undefined
  • May let a prototype property shine through

    person['first-name'] = 'Jason';
    person['first-name']             // 'Jason'
    
    delete person['first-name']
    person['first-name']             // 'John'

Objects: Reducing Global Footprint

  • A single global variable for your application

    var MyAPP = {};
  • Contains all your variables (as properties)

    MyAPP.someone = {'first-name': 'John', 'last-name': 'Doe'};
    MyApp.person = Object.create(MyAPP.someone);

Functions

  • The best thing in JavaScript

  • A function encloses a set of statements that execute when invoked

  • Functions are objects

    • Linked to a prototype (Function.prototype)

    • Can be stored in variables, objects, and arrays

    • Can be passed as arguments to functions and can be returned from functions

  • A function has a prototype property

  • Uses:

    • Code reuse, Information hiding, Composition

Functions: Function Literal

  • 4 parts:

    1. function (reserved word)

    2. name (optional)

    3. parameters

    4. body

    var add = function (a, b) {
      return a + b;
    };

Functions: Invocation

  • Extra parameters: this & arguments

  • Invocation Patterns

    1. Method invocation pattern

    2. Function invocation pattern

    3. Constructor invocation pattern

    4. Apply invocation pattern

  • Arguments

    • No error if not matching number of parameters

    • Extra arguments are ignored

    • Missing will be undefined

Functions: Method Invocation Pattern

  • Function is stored as a property of an object

  • this will be the object

    var myObject = {
      value: 0,
      increment: function (inc) {
        this.value += inc;
      }
    };
    
    myObject.increment(2);
    
    myObject.value;                      // 3

Functions: Function Invocation Pattern

  • Function is not a property of an object

  • this will be the global object (design mistake)

    myObject.double = function () {
      var that = this;      // Workaround.
      var helper = function () {
        that.value = 2 * that.value
      };
      helper();             // Invoke helper as a function.
    };
    
    myObject.double();      // Invoke double as a method.
    myObject.getValue();    // 4

Functions: Constructor Invocation Pattern

  • Invoked with new prefix

  • A new object is created & linked to function's prototype property

  • this is bound to the new object

    var Car = function (speed) {
      this.speed = speed;
    };
    
    Car.prototype.move = function() {
      return 'moving at ' + this.speed;
    };
    
    var my_car = new Car('40 k/h');
    
    my_car.move();                 // moving at 40 k/h
          

Functions: Apply Invocation Pattern

  • apply is a method of functions

  • 2 parameters: value for this & array of arguments

    var util = {
      get_status: function(uppercase){
        return uppercase ?
          this.status.toUpperCase() : this.status;
      }
    };
    
    var obj = { status: 'ok' };
    
    util.get_status.apply(obj, [true]);      // 'OK'

Functions: Arguments

  • arguments: array of parameters passed to a function

  • array-like object

    
    var sum = function () {
      var i, s = 0;
      for (i = 0; i < arguments.length; i += 1) {
          s += arguments[i];
      }
      return s;
    };
    
    sum(4, 8, 15, 16, 23, 42)         // 108
    

Functions: Return

  • Functions always return a value

  • If no return value is given undefined is returned

  • If invoked with new and no return is given the new object is returned

    var Car = function (speed) {
      this.speed = speed;
    };
    
    var my_car = new Car('40 k/h');
    

Functions: Scope

  • No block scope

  • Only function scope

    var foo = function () {
      var a = 3, b = 5;
    
      var bar = function () {
        var b = 7, c = 11;
        a += b + c;
      };
    
      bar();
    };

Functions: Closure

  • Inner functions have access to outer function's parameters and variables.

    var elevator_maker = function() {
      var level = 1;
      var get_level = function() { return "level: " + level; }
    
      return {
        up:   function(n) { level += n; return get_level(); },
        down: function(n) { level -= n; return get_level(); },
      };
    };
    
    var elevator = elevator_maker();
    
    elevator.up(3);                    // level: 4
    elevator.down(1);                  // level: 3

Functions: Module

  • Can eliminate the use of global variables

    var elevator = function() {
      var level = 1;
      var get_level = function() { return "level: " + level; }
    
      return {
        up:   function(n) { level += n; return get_level(); },
        down: function(n) { level -= n; return get_level(); },
      };
    }();
    
    elevator.up(3);                    // level: 4
    elevator.down(1);                  // level: 3

Functions: Memoization

  • Remember the results of previous operations

    var fibonacci = function (n) {
      return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
    };      
    
    var fibonacci = function () {
      var memo = {0: 0, 1: 1};
      return function fib (n) {
        var result = memo[n];
        if (typeof result !== 'number') {
          result = fib(n - 1) + fib(n - 2);
          memo[n] = result;
        }
        return result;
      };
    }();
    
    fibonacci(10)             // 55

Inheritance: Pseudoclassical

  • Intended to look sort of object-oriented

  • Provided by using new prefix

  • Hides the true nature of the language

    var Vehicle = function(name){ this.name = name; };
    Vehicle.prototype.get_name = function(){ return this.name; };
    
    var vehicle = new Vehicle('Just a ride');
    
    var Car = function(name, racing){
      this.name = name;
      this.racing = racing;
    };
    Car.prototype = vehicle;
    
    var my_car = new Car('My car', false);
    my_car.get_name();            // 'My car'
    my_car.racing;                // false

Inheritance: Prototypal

  • A new object can inherit the properties of an old object

  • Start with a useful object and then make many more like it

    var vehicle = {
      name: 'Just a ride',
      get_name: function(){ return this.name; }
    };
    
    var my_car = Object.create(vehicle);
    my_car.name = 'My car'
    my_car.racing = false;
    
    my_car.get_name();            // 'My car'
    my_car.racing;                // false

Inheritance: Functional

  • Allows privacy

    var vehicle = function(spec) {
      spec.name = spec.name || 'Just a ride';
      var that = {};
    
      that.get_name = function(){ return spec.name; };
    
      return that;
    };
    
    var car = function(spec) {
      spec.racing = !! spec.racing;
      var that = vehicle(spec);
    
      that.is_racing = function(){ return spec.racing; };
    
      return that;
    };
    
    my_car = car({name: 'My car', racing: false});
    
    my_car.get_name();            // 'My car'
    my_car.is_racing();           // false

Arrays

  • Array-like objects

  • Linked to Array.prototype

  • No linear allocated memory or computed offest access

  • Have their own literal notation

  • Elements can be of any value

Arrays

  • Array literal

    var a = [];
    var misc = [ 'string', 98.6, true, null, undefined,
      ['nested', 'array'], {x: 1}, Infinity ];
    
  • length property is not upper bound

    var a = [];
    a.length          // 0
    a[10] = 1;
    a.length          // 11
    a[4]              // undefined
  • Have methods

    var a = [];
    a.push(1);
    a                 // [1] 

Bad parts

  • Global variables

  • No block scope

  • Semicolon insertion

    return
    {
      status: true
    };      
          
    return {
      status: true
    };

Bad parts

  • floating point

  • Phony arrays

  • + overloading

    1 + 2               // 3
    '1' + 2             // '12'
    1 + '2'             // '12'
  • typeof

    typeof null         // object
    typeof []           // object
    

Bad parts

  • eval

  • Bitwise operators

  • ==

    '' == '0'          // false
    0 == ''            // true
    0 == '0'           // true
    false == 'false'   // false
    false == '0'       // true
    false == undefined // false
    false == null      // false
    null == undefined  // true
    ' \t\r\n ' == 0    // true
          

References

  • JavaScript: The Good Parts

    by Douglas Crockford

Thank You