block by roachhd 12cd60e8f96958d11435

JAVASCRIPT - The Good Bits. slideshow with markdown

Full Screen

index.html

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
    <title>JavaScript: The Good Parts</title>
    <script src="//gnab.github.io/remark/downloads/remark-0.5.9.min.js" type="text/javascript"> </script>
    <style type="text/css" media="screen">
      @import url(//fonts.googleapis.com/css?family=Droid+Serif);
      @import url(//fonts.googleapis.com/css?family=Yanone+Kaffeesatz);

      body { font-family: 'Droid Serif'; }
      h1, h2, h3 {
        font-family: 'Yanone Kaffeesatz';
        font-weight: 400;
        margin-bottom: 0;
        margin-top: 10px;
      }
      h1 { font-size: 3.5em; }
      h2 { font-size: 3em; }
      h3 { font-size: 1.6em; }
      .inverse {
        background: #272822;
        color: #777872;
        text-shadow: 0 0 20px #333;
      }
      .inverse h1, .inverse h2 {
        color: #f3f3f3;
        line-height: 0.8em;
      }

      pre {
        border-left: 0.4em solid #d7d7d7;
        padding: 1em !important;
      }
      code {
        background: transparent !important;
      }
      a {
        color: #F92672;
        text-decoration: none;
      }
      .task {
        float: right;
        font-size: 0.9em;
        padding-top: 0.6em;
      }
      .task a {
        color: #080;
        text-decoration: none;
      }
      .right {
        float: right;
        margin-left: 1em;
      }
      .pushdown {
        margin-top: 12em;
      }
    </style>
  </head>
  <body>
    <textarea id="source">
class: center, middle, inverse

# JavaScript: The Good Parts

### by [@gnab](//twitter.com/gnab) &amp; [@torgeir](//twitter.com/torgeir)

---

# The Book

.right[![JavaScript: The Good Parts](thebook.png)]

Short, exclusively about JavaScript.

- "_Intended for programmers venturing into JavaScript for the first time_"

- "_... also indented for programmers who have been working with JavaScript at a novice level, and are now ready for a more sophisticated relationship with the language_"

- "_This is not a book for beginners_"

- "_This is not a book for dummies_"


???

- Crockford som har skrevet både bok og JSLint (luke ut ulumskheter)
- editorjs - online editor m/ oppgaver, kjøring og linting
- Fokus kun på språk, ikke rammeverk / arkitektur

---
class: center, middle

## Editor
### [//js-workshop.herokuapp.com](//js-workshop.herokuapp.com)

## Slides
### [//gnab.github.com/js-workshop](//gnab.github.com/js-workshop)

## Code
### [//github.com/gnab/js-workshop](//github.com/gnab/js-workshop)

---
name: default
layout: true
task: &nbsp;

.task[{{task}}]

---
class: center, middle, inverse

# Object Literals

???

Objekter, arrays og typer
---
template: default
layout: true

### Object Literals

---
task: [#01 Object properties](//js-workshop.herokuapp.com/#1/1)

# Objects

A collection of key-value properties.

    var obj = {
      key1: 'value1',
      key2: 13
    };

    obj.key1;         // 'value1'
    obj['key2'];      // 13
    obj.key3;         // undefined

    delete obj.key1;
    obj.key1;         // undefined

???

- Aksess av felter både ved . og []
- Manglende felt gir undefined, ikke feil

---
task: [#02 Populating arrays](//js-workshop.herokuapp.com/#1/2)

# Arrays

A collection of indexed properties.

    var arr = [1, "two", 3];

    arr.push(4);

    arr[1];         // "two"
    arr[3] = 4;
    arr.length;     // 4

???

- Dynamisk størrelse
- Vilkårlige typer objekter
- .length

---

# Objects vs. Arrays (1/2)

Arrays are not "real":

- Objects in disguise
- Operations are slow when number of elements are large


    var obj = [1, 2, 3];
    obj.speed = 5;

    obj[1];         // 2
    obj.speed       // 5
    obj['speed'];   // 5

    obj.length;     // 3

???

.length baserer seg på "array" innhold, ikke andre felter

---
task: [#03 What have you got?](//js-workshop.herokuapp.com/#1/3)

# Objects vs. Arrays (2/2)

The `for (... in ...)` loops all properties of an object.

    var obj = [1, 2, 3];
    obj.speed = 5;

    var i;
    for (i = 0; i < obj.length; ++i) {
      obj[i];  // 1, 2, 3
    }

    var key;
    for (key in obj) {
      obj[key];  // 1, 2, 3, 5
    }

---
task: [#04 Who are you?](//js-workshop.herokuapp.com/#1/4)

# Types

Go figure.

    new Object();       // {}
    new Array();        // []
    new Number(1);      // 1
    new Boolean(true);  // true

    typeof {};          // 'object'
    typeof [];          // 'object'     WTF?
    typeof 1;           // 'number'
    typeof '';          // 'string'
    typeof true;        // 'boolean'

    typeof null;        // 'object'     WTF?

???

- Foretrukket å ikke bruke new (kan utelates og gi feil resultat)
- typeof [] gir mening, men kan ikke skille typene
- typeof gir alltid streng
- typeof må brukes for å sjekke eksistens (men ikke for objektfelter)

---
layout: false
class: center, middle, inverse

# Functions

---
template: default
layout: true

### Functions
---

# You name it

    function () {}

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

    var multiply = function (a, b) {
      return a * b;
    };

    var recur = function rec (num) {
      if (num === 0) { return num; }
      return rec(num - 1);
    };

???

- Function expressions vs statements
- Hoisting - add tilgjengelig overalt
- Kan lagre (anonyme) funksjoner i variabler
- Navngitt funksjon privat ved tilordning (recur / rec)

---
task: [#01 How many arguments do you have?](//js-workshop.herokuapp.com/#2/1)

# arguments

All functions can access their:

- `arguments`
  - `length`
  - `callee`


    function countArgs () {
      return arguments.length;
    }

    countArgs();              // 0
    countArgs('one');         // 1
    countArgs('one', 'two');  // 2

???

- arguments ikke array, men objekt med length-felt
- callee - funksjonen selv, den som blir kalt
- Oppgave løses med for, ikke for in
- Siste definisjon av funksjon med samme navn gjelder
- Funksjon kan kalles med vilkårlig antall argumenter uavh. av definisjon

---
task: [#02 Higher order functions](//js-workshop.herokuapp.com/#2/2)

# First order variables

- Functions can return functions
- Functions can take functions as an argument


    function createFunction () {
      return function () {

      };
    }

    var anonymous = createFunction();
    anonymous();  // undefined

---

# Scope (1/2)

JavaScript has __function scope__, not block scope.

    function () {
      i;  // undefined    WTF?

      for (var i = 0; i < 10; i++) {

      }

      i;  // 10
    }

???

Uten var i hadde man fått ReferenceError

---

# Scope (2/2)

Variable declarations towards the top, please!

    function () {
      var i;

      for (i = 0; i < 10; i++) {

      }

      i;  // 10
    }

???

Hoisting - skjer implisitt, så greit å gjøre synlig

---

# More on scope (1/3)

Functions can access everything from their outer scope.

    var a = 1;

    function doSomething () {
      a;  // 1

      function doMore () {
        a;  // 1
      }
    }

---

# More on scope (2/3)

Not the other way around.

    function doSomething () {
      var b = 1;

      function doMore () {
        b;  // 1
      }
    }
    doSomething();

    b;  // ReferenceError

???

Funksjon kan kjøres når expression - vanlig med () rundt for å gjøre til expr.

---
task: [#03 JavaScript pwns your scope](//js-workshop.herokuapp.com/#2/3)

# More on scope (3/3)

Forgot the __`var`__? You've got yourself a global!

    function doSomething () {
      c = 1;

      function doMore () {
        c;  // 1
      }
    }
    doSomething();

    c;  // 1

---
task: [#04 Variables by reference](//js-workshop.herokuapp.com/#2/4)<br /> [#05 Binding scope](//js-workshop.herokuapp.com/#2/5)

# Closures (1/3)

Functions can bind scope, even after their outer function has returned!

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

      return function () {
        return i++;
      };
    };

    var inc = counter();
    inc();  // 0
    inc();  // 1

---
task: [#06 Globally ugly, privately slow, closingly sweet](//js-workshop.herokuapp.com/#2/6)<br />[#07 Variables by reference](//js-workshop.herokuapp.com/#2/7)

# Closures (2/3)

Functions can run immediatly!

    var inc = function () {
      var i = 0;

      return function () {
        return i++;
      };
    }();  // Note the trailing ()!

    inc();  // 0
    inc();  // 1

---

# Closures (3/3)

Create modules with private state!

    var lib = {};
    lib.module = (function () {

      var privateVariable;

      var privateFunction = function () {};

      return {
        publicProperty: 1,
        privilegedMethod: function (arg) {
          // privateVariable = arg;
        }
      };

    })();

---

# Context

- Functions run in different contexts
  - Depending on how they are invoked

- May be invoked in 4 primary ways
  - Function invocation
  - Constructor invocation
  - Method invocation
  - `apply`/`call` invocation

---
task: [#08 What is this?](//js-workshop.herokuapp.com/#2/8)

# Function invocation

Functions called directly.

    var countArgs = function () {
      // this === window

      return arguments.length;
    };

    countArgs();  // 0

???

I nodejs ville this ikke være window, men exports.

---
task: [#09 Constructing objects](//js-workshop.herokuapp.com/#2/9)

# Constructor invocation (1/2)

Functions called with the __`new`__ keyword.

    function Person (name) {
      // this === instance of Person

      this.name = name;
    }

    var bob = new Person('bob');
    var ed = new Person('ed');

    ed.name = 'fred';

---

# Constructor invocation (2/2)

But there's a gotcha!

    function Person (name) {
      this.name = name;
    }

    var bob = Person('bob');
    var ed = new Person('ed');

    window.name === 'bob'  // true    WTF?

---
task: [#10 Context confusion](//js-workshop.herokuapp.com/#2/10)

# Method invocation

Functions called on objects.

    var obj = {
      value: 1,
      getValue: function () {
        // this === obj

        return this.value;
      }
    };

    obj.getValue()  // 1

---
task: [#11 Is this yours?](//js-workshop.herokuapp.com/#2/11)

#  apply/call invocation

Applying functions to objects.

    function doStuff () {
      return this.speed;
    }

    var obj = { speed: 2 };

    doStuff.apply(obj, [ arg1, arg2 ]);  // 2

    doStuff.call(obj, arg1, arg2);     // 2

---
layout: false
class: center, middle, inverse

# Inheritance

---
layout: true
template: default

### Inheritance
---

# Multiple paradigms

- Pseudoclassical inheritance

- Prototypal/differential inheritance

- Functional inheritance

???

- Ullent område
- Mange gjør forskjellig
- Prøver å etterligne andre språk
- JavaScript kan tilpasses flere paradigmer

---

# Prototype (1/3)

- Inherit directly from other objects
  - Properties
  - Methods

- All objects inherit from a `prototype` property

- Bound upon object creation


    var obj = {};
    obj.toString();  // '[object Object]'

---

# Prototype (2/3)

The `prototype` property.

    function Object () {}

    Object.prototype = {
      toString: function () {
        return '[object Object]';
      }
    };

    var obj = new Object();
    obj.toString();  // '[object Object]'

---

# Prototype (3/3)

    var first = new Object();
    // first.__proto__ = Object.prototype;

    first.x = 1;       // on first
    first.toString();  // on first's prototype (Object)

![Prototypal Inheritance 1](prototype1.png)

---
task: [#01 Pseudoclassical 1](//js-workshop.herokuapp.com/#3/1)

# Pseudoclassical inheritance (1/2)

.right.pushdown[![Prototypal Inheritance 2](prototype2.png)]

    function CoolObject (x) {
      this.x = x;
    }

    CoolObject.prototype = {
      getX : function () {
        return this.x;
      }
    };

    var coolObj = new CoolObject(1);

???

- Prototype-objektet deles av alle instanser, hvert objekt arver ikke alt
- Minner om statiske klassevariabler/metoder
- Kan endre ting på prototypen i etterkant - vil påvirke alle instanser
- Kan endre prototype for objekt etter opprettelse
- Husk at = { .. tilsvarere new Object()

---
task: [#02 Pseudoclassical 2](//js-workshop.herokuapp.com/#3/2)

# Pseudoclassical inheritance (2/2)

- Intented to look object oriented - looks quite alien?

- Remember to use __`new`__!
 - Clobbering global variables
 - No compile warning, no runtime warning
 - Convention - all constructor functions start with an capital letter

"_Comfort to unexperienced JavaScript programmers_"
"_Induce unnecessary complex hierarcies_"
"_... motivated by constraints of static type checking_"

__JavaScript has more and better options__

???

- Bedre å pakke inn new for å unngå å etterligne andre språk
- Veldig likt obj := Object clone i Io

---
task: [#03 Prototypal](//js-workshop.herokuapp.com/#3/3)

# Prototypal/differential inheritance

- Dispence with classes, make useful objects
- Specify differences


    function create (proto) {
      function F () {};
      F.prototype = proto;
      return new F();
    }

    var eventBase = {
      emit: function () {},
      on: function () {}
    };

    var obj = create(eventBase);
    obj.emit('some event');

---
task: [#04 Functional](//js-workshop.herokuapp.com/#3/4)

# Functional inheritance (1/2)

    var person = function (options) {
      var that = {};

      that.getName = function () {
        return options.name;
      };

      return that;
    };

    var bob = person({ name: 'bob' });
    var ed = person({ name: 'ed' });

???

Ulempe at alle instanser får egne kopier av funksjoner

---

# Functional inheritance (2/2)

    function Car (options) {

      this.getColor = function () {
        return options.color;
      };
    }

    Car.proto...

    var car = new Car({ color: 'red' });
    car.getColor(); // 'red'

---
layout: false
class: center, middle, inverse

# Bad Parts

---
layout: true
template: default

### Bad Parts
---

# Arrays

Indices are free to go.

    var arr = [1, 2, 3];
    arr[999] = 0; // WTF
    arr.length;   // 1000

    delete arr[1];
    arr; // [1, undefined, 3];

???

Sletting må gjøres med splice(1,1) (fjern ett element fra posisjon 1)

---

# for (... in ...)

Properties from the `prototype` chain are looped as well.

    var key;

    for (key in obj) {
      if (obj.hasOwnProperty(key)) {
        // Property belongs to obj itself
      }
    }

---

# eval is evil

Property look-ups.

    // Don't do
    eval('var value = obj.' + key);

    // Rather do
    var value = obj[key];

Function references.

    // Don't do
    var f = new Function("alert('hello');");
    setTimeout("alert('hello')", 1000);
    setInterval("alert('hello')", 1000);

    // Rather do
    var f = function () { alert('hello'); };
    setTimeout(f, 1000);

---

# Falsy values

- __`false`__
- __`null`__
- __`undefined`__
- `0` (zero)
- `''` or `""` (empty string)
- __`NaN`__ (not-a-number, e.g. 'a' / 2)


`&&` and `||` return the actual value of the expession that stops the evaluation:


    function Car (name) {
      this.name = name || 'default name';
    }

---

# Transitivity - come again?

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

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

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

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

---

# Semicolon insertion (1/2)

    function getStatus () {
      return
      {
        status: true
      }
    }

---

# Semicolon insertion (2/2)

    function getStatus () {
      return;                             <- semicolon insertion
      {                                   <- open block
        status: true                      <- loop label
      }                                   <- close block
    }


# W T F

---

# arguments is not an array

It only pretends to be.

    {
      '0': 1,
      '1': 2,
      length: 2
    }

But you can fix it.

    function f () {
      var slice = Array.prototype.slice; // [].slice
      return slice.apply(arguments);
    }

    f(1, 2);  // [1, 2]

---

# Keywords

    obj[&lt;keyword&gt;] = 1  // Reserved word (undefined, NaN, Infinity?)

- `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`__

---

# Avoid void

Void is not useful, avoid void!

- __`void`__ is an operator
- takes an operand
- returns __`undefined`__

` `

    void 1  // undefined

---
layout: false
class: center, middle, inverse

# That's all folks!

Slideshow created with [remark](//gnab.github.com/remark).

    </textarea>
    <script>
      var slideshow = remark.create({ highlightLanguage: 'javascript'});
    </script>
  </body>
</html>