59
Javascript The Good Parts Gabriele Lana [email protected] Federico Galassi [email protected]

Javascript The Good Parts

Embed Size (px)

DESCRIPTION

By Federico Galassi and Gabriele Lana at PHPCon Italia 2009 See http://federico.galassi.net/2009/05/17/javascript-the-good-parts-talk/ Follow me on Twitter! https://twitter.com/federicogalassi

Citation preview

Page 2: Javascript The Good Parts

Why Javascript

The language of the Web A nice, elegant, expressive

language

2

Page 3: Javascript The Good Parts

Why Javascript

A nice, elegant, expressive language... What??

3

Page 4: Javascript The Good Parts

Javascript perceived as a toy language

Good for small quick web hacks Not good for “serious” programming

large projects mantainable code

4

Page 5: Javascript The Good Parts

Javascript is a toy language? Bullshit!!

Stanford UniversityCS 242 “Programming Languages” 2008

Mozilla Corporation Firefox

Many more...

5

Page 6: Javascript The Good Parts

Javascript is not toy language...So what?

The Most Misunderstood language ever Different from mainstream Design mistakes Traditionally runs in the browser

6

Page 7: Javascript The Good Parts

Javascript is different

Not the language you already know You already know other good languages It’s a web designer thing, it’s “easy” Copy&Paste Oriented Programming

7

!=

Page 8: Javascript The Good Parts

Javascript is different

Hidden nature Familiar syntax from Java/C Pretty exotic foundations

Objects from Self Functions from Scheme

8

if (x < 1) { x++;}

Page 9: Javascript The Good Parts

Javascript has design mistakes

Short lab time hacked in one week in may 1995 in netscape2 by the end of the year

Too fast adoption web boom

Controversial goals “easy” for non programmers must look like java

No fixes since 1999

9

Brendan EichCreator of JavascriptMozilla CTO

Page 10: Javascript The Good Parts

Javascript usually runs in the browser

Inconsistent implementations poor specifications

Depends on DOM for I/O and it sucks!

Lack of common features file system access sockets “require”

No standard libs

10

Page 11: Javascript The Good Parts

Javascript rules indeed!

Imperative Functional Object Oriented Simple Winner by natural selection

...where java failed.

11

DachshundEvolution

Page 12: Javascript The Good Parts

Javascript can be made even better!

Javascript has good and bad parts Use good parts the “right way” Cut bad parts ...Beautiful code

12

BEFORE

AFTER

Page 13: Javascript The Good Parts

Javascript the different good parts:Functions First class

are objects can be created at runtime can be stored in variables can be passed as parameters to functions can be returned by functions can be expressed as anonymous literals

13

Page 14: Javascript The Good Parts

Javascript the different good parts:Working with Functions 1

14

// Creation the old wayfunction hello(name) { return "hello " + name;}

// Creation the good wayvar hello = function(name) { return "hello " + name;};

// Invocationhello; // returns function()hello("world"); // returns "hello world"

// Self Invocation(function(name) { return "hello " + name })("world");

Page 15: Javascript The Good Parts

// Passed as parameter and invokedvar helloWorld = function() { print "hello world!" };var twice = function(func) { func(); func();};

twice(helloWorld); // prints "hello world!hello world!"

// Returned by a functionvar makeHello = function() { return function(name) { return "hello " + name; }};

var hello = makeHello();hello("world"); // returns "hello world"

Javascript the different good parts:Working with Functions 2

15

Page 16: Javascript The Good Parts

Javascript the different good parts:Functions and Scope Scopes

Global Function No

Block-level Call

Objects Scope

Chain

16

var x = 1,

y = 2;

function outer(p) {

var z = 3;

}

function inner() {

var x = 100,

w = 200;

}

x = 1

y = 2

v = 3

z = 3

p = ...

x = 100

w = 200

Scope Chain

Global

Function

if (true) {

var v = 3;

}

Page 17: Javascript The Good Parts

Javascript the different good parts:Functions as Closures 1 Lexical Scoping Closures

17

z = 100

z = 3

Scope Chain

Global

function outer() {

var z = 3;

return

}

function() {

return z;

}

Function

var inner = outer();

var z = 100;

inner(); // returns 3 Execution

Page 18: Javascript The Good Parts

Javascript the different good parts:Functions as Closures 2 Closures bind variables, not values !

18

// Wrongvar funcs = [];for (var i = 0; i < 3; i++) { funcs[i] = function() { return i; }}

funcs[0](); // returns 3 !!funcs[1](); // returns 3 !!funcs[2](); // returns 3 !!

// Rightvar funcs = [];for (var i = 0; i < 3; i++) { funcs[i] = function(p) { return function() {return p}; }(i)}

funcs[0](); // returns 0funcs[1](); // returns 1funcs[2](); // returns 2

Page 19: Javascript The Good Parts

Javascript the different good parts:Objects 1 Containers of key/value pairs (properties)

keys are strings values are anything (loose typing)

19

book

-"author"

"Javascript"

240

"title"

"pages"

"surname"

"Federico""name"

"Galassi"

// Creation with literalvar book = { title: "Javascript", pages: 240, author: { name: "Federico", surname: "Galassi" }}

Page 20: Javascript The Good Parts

Javascript the different good parts:Objects 2 Objects are dynamic

Properties can be added and removed at runtime No class constraints

20

// Get a propertybook["title"] // returns "Javascript"book.title // same as book["title"]book.propertyNotThere // returns undefined

// Set or update a propertybook.cover = "butterfly.jpg"book.title = "Javascript the good parts"

// Delete a propertydelete book.title // now book.title is undefined

Page 21: Javascript The Good Parts

Javascript the different good parts:Objects Methods Methods are

function valuedproperties

Inside methodsthis is bound toobject “on the left”

21

book.read = function() { var action = "Reading "; return action + this.title;}

book.read(); // returns "Reading Javascript"

book

-"read"

"Javascript"

240

"title"

"pages"

function() {

var action = "Reading ";

return action + this.title;

}

Method

action = "Reading "

Scope

this =

Page 22: Javascript The Good Parts

Javascript the different good parts:Objects Prototype Every object can be linked to another object

through the prototype property (__proto__) If a property does not exist in the object, request is

delegated to the prototype

22

another_point

__proto__ -

20"x"

point

-__proto__

10

10

"x"

"y"

var point = { x: 10, y: 10};var another_point = { x: 20};another_point.__proto__ = point;point.x; // returns 20point.y; // returns 10 (delegated)

Page 23: Javascript The Good Parts

Javascript the different good parts:Objects Prototype and Methods Delegation works for methods too this is always bound to the “first object”

23

// returns 20 * 10 = 200another_rect.area();

another_rect

__proto__ -

20"width"

rect

-__proto__

-"area"

10

10

"width"

"height" function() {

return this.width *

this.height;

}

Method

Scope

this = Prototype

Page 24: Javascript The Good Parts

Javascript the different good parts:Objects Prototype Chain Prototypes form a chain, followed to resolve

properties At the end there is Object which provides common

stuff, then undefined

24

first.asdasdasd;// "asdasdasd" not in first,// second, last// "asdasdasd" not in {}// returns undefined

first.hasOwnProperty// returns function() ...

first__proto__ -

second__proto__ -

last__proto__ -

Object

Property

Resolution

Page 25: Javascript The Good Parts

var car = { color: "white", speed: 0, accel: function(kmh) { this.speed += kmh; }};

// Make a supercar from carvar supercar = { color: "black", __proto__: car};

// or also by cloningvar supercar = Object.create(car, { color: "black"});

Javascript the different good parts:Working with Objects and Prototypes 1

25

Page 26: Javascript The Good Parts

// Prototype relationship is dynamiccar.wheels = 4;supercar.wheels; // 4

// Setting properties is localsupercar.driver = "M. Knight";car.driver; // undefined

// Where properties are from?"driver" in supercar; // true"wheels" in supercar; // truesupercar.hasOwnProperty("driver"); // truesupercar.hasOwnProperty("wheels"); // false

// Common to all objectssupercar.toString(); // "[object Object]"car.isPrototypeOf(supercar); // true

Javascript the different good parts:Working with Objects and Prototypes 2

26

Page 27: Javascript The Good Parts

Javascript the different good parts:Objects Prototypal Inheritance 1 Prototypes are javascript way to share

Data Behaviour

27

Page 28: Javascript The Good Parts

Javascript the different good parts:Objects Prototypal Inheritance 2 Prototypal Inheritance

Vs Classical Inheritance Simpler

No classes and objects, only objects Easier

Work by examples, not abstractions Powerful !!

Can simulate classical Reverse not true

Shhhh, Don’t tell anyone Easier to write spaghetti code

28

Page 29: Javascript The Good Parts

Javascript the different good parts:Objects Prototypal Inheritance 3 Ok, I cheated

__proto__ available in mozilla only Object.create coming in next revision of language

Javascript is schizophrenic Prototypal nature Wannabe classical

29

Page 30: Javascript The Good Parts

Javascript the different good parts:Objects Constructor Functions 1 Constructor Functions

Boring Function has a “prototype” property The “prototype” property has a

“constructor” property which pointsback to the Function object

Function can be invoked with the“new” operator

Create an object whose __proto__is “prototype” property of Function

Initialize the object executing Function

30

Page 31: Javascript The Good Parts

// Constructor function // silently executesfunction Dog(name) { // Dog.prototype = { constructor: Dog } this.name = name;}

Dog.prototype; // ObjectDog.prototype.constructor; // return function Dog

// Create a new Dog object // silently executesvar fido = new Dog("fido"); // var fido = Object.create(Dog.prototype); // Dog.call(fido, "fido");

fido.__proto__; // Objectfido.__proto__.constructor; // Dogfido.constructor; // Dog (inherited by __proto__)fido.name // fido

Javascript the different good parts:Objects Constructor Functions 2

31

Page 32: Javascript The Good Parts

Javascript the different good parts:Objects Constructor Functions 3 Why?

Function is a constructor Function prototype is a class new is new Feels classical, Feels familiar

Worst of both worlds Unnecessarily complicated Hide prototypal nature Weird for classical programmers

32

function Rectangle(w, h) { this.w = w; this.h = h;}Rectangle.prototype.higher =function() { this.h += 1 };

var rect = new Rectangle(5,10);

Page 33: Javascript The Good Parts

Javascript the different good parts:Objects Constructor Functions Fix Fortunately there’s a Quick Fix

33

// waiting for next javascript implementation...

if (typeof Object.create !== 'function') { Object.create = function (o) { var F = function() {}; F.prototype = o; return new F(); };}

Page 34: Javascript The Good Parts

Javascript the different good parts:Arrays No real arrays in javascript They’re objects in disguise

special props and methods Cool literal syntax

34

Page 35: Javascript The Good Parts

// array literalvar numbers = [1, 2, 3, 4, 5];

// referencenumbers[2]; // returns 3numbers[10]; // returns undefined

// length propertynumbers.length; // 5

// nice methodsnumbers.push(11); // now [1, 2, 3, 4, 5, 11]numbers.join(" "); // returns "1 2 3 4 5 11"

Javascript the different good parts:Arrays Example 1

35

Page 36: Javascript The Good Parts

// actually...

// indexes are just object propertiesnumbers.2; // would return 3

// common object methodsnumbers.hasOwnProperty(0); // returns true

// length = last numeric prop + 1numbers[100] = 100;numbers.length; // returns 101

// ultimate prooftypeof numbers; // returns "object"

Javascript the different good parts:Arrays Example 2

36

Page 37: Javascript The Good Parts

Javascript the different good parts:Functional Programming Iterators Callbacks Module Pattern Curry Memoization

37

Page 38: Javascript The Good Parts

Javascript the different good parts:Functional Programming Iterators Take control of loops Reduce accidental complexity

38

Page 39: Javascript The Good Parts

// iterate on a collection

function each(arr, func) { for (var i=0; i<arr.length; i++) { func(arr[i]); }}

var ten = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

each(ten, function(i) { print i;});// prints 12345678910

Javascript the different good parts:Iterators Example 1

39

Page 40: Javascript The Good Parts

// maps a collection to a new one

function map(arr, func) { var result = []; each(arr, function(i) { result.push(func(i)); }); return result;}

var ten = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

map(ten, function(i) { return i * i; });// returns [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

Javascript the different good parts:Iterators Example 2

40

Page 41: Javascript The Good Parts

// filter elements of a collection

function filter(arr, func) { var result = []; each(arr, function(i) { if (func(i)) { result.push(i); } }); return result;}

var ten = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

filter(ten, function(i) { return i % 2 === 0; });// returns [2, 4, 6, 8, 10]

Javascript the different good parts:Iterators Example 3

41

Page 42: Javascript The Good Parts

// compute a single value from a collection

function reduce(arr, func, start) { var result = start; each(arr, function(i) { result = func(i, result); }); return result;}

var ten = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

reduce(ten, function(i, sum) { return i + sum;});// returns 55

Javascript the different good parts:Iterators Example 4

42

Page 43: Javascript The Good Parts

// Composability// square elements, then pick even ones, then sum

reduce( filter( map(ten, function(i) { return i * i; } ), function(i) { return i % 2 === 0; } ), function(i, sum) { return i + sum; }, 0);

Javascript the different good parts:Iterators Example 5

43

Page 44: Javascript The Good Parts

// Composability but easy to read

var square = function(arr) { return map(arr, function(i) { return i * 2; });}var even = function(arr) { return filter(arr, function(i) { return i % 2 === 0; });}var sum = function(arr) { return reduce(arr, function(i, total) { return i + total; }, 0);}

sum(even(square(ten)));

Javascript the different good parts:Iterators Example 6

44

Page 45: Javascript The Good Parts

Javascript the different good parts:Functional Programming Callbacks Manage asynchronous communication Hide complexity

45

Page 46: Javascript The Good Parts

// Synchronous request

var response = get("http://www.google.com");display(response);

// Asynchronous with callback

get("http://www.google.com", function(response) { display(response); });

Javascript the different good parts:Callbacks Example 1

46

Page 47: Javascript The Good Parts

// explicit complexityvar response = get("http://www.google.com");if (response.completed) { if (response.httpCode === "200") { display(response); } else { // http error }} else { // network error}

Javascript the different good parts:Callbacks Example 2

47

Page 48: Javascript The Good Parts

// complexity hidden in the client codevar response = get("http://www.google.com");if (success(response)) { display(response);} else { // error}

// complexity hidden awayget("http://www.google.com", { success: function(response) { display(response); }});

Javascript the different good parts:Callbacks Example 3

48

Page 49: Javascript The Good Parts

Javascript the different good parts:Functional Programming Module Pattern Hide state and behaviour

49

Page 50: Javascript The Good Parts

var numbers = ["zero", "one", "two", "three", ...]; // GLOBAL BADvar numberToString = function(num) { return numbers[num];}

var numberToString = function(num) { // LOCAL SLOW var numbers = ["zero", "one", "two", "three", ...]; return numbers[num];}

var numberToString = function() { // PRIVATE AND FAST var numbers = ["zero", "one", "two", "three", ...]; return function(num) { return numbers[num]; }}();

Javascript the different good parts:Module Pattern Example 1

50

Page 51: Javascript The Good Parts

Javascript the different good parts:Functional Programming Memoization Cache computation Speed up execution

51

Page 52: Javascript The Good Parts

// get pixels. maybe millions of themvar pixels = getImagePixels("image.jpg");

var getColor = function(pixel) { // ... computation on RGB values ... returns "black"; // or "white" or "green" etc...}

// find the colorpixels.each(function(pixel) { var color = getColor(pixel); // store result});

Javascript the different good parts:Memoization Example 1

52

Page 53: Javascript The Good Parts

// wasted computation, cache it...var getColorCache = function(func) { var cache; // setup cache ... return function(pixel) { if (cache.missing(pixel)) { cache.store(pixel, func(pixel)); } return cache.get(pixel); }}(getColor);

Javascript the different good parts:Memoization Example 2

53

Page 54: Javascript The Good Parts

Javascript the bad parts

The features you should definitely avoid

54

Page 55: Javascript The Good Parts

Javascript the bad parts 1

Global variables Semicolon insertion

Reserved words

55

// Good, returns { ok: true } // Very bad, returns undefinedreturn { return ok: true {} ok: true }

// Good // Very bad, errorbook["class"]; book.class;var book = { var book = { "class": "book" class: "book" } }

Page 56: Javascript The Good Parts

Javascript the bad parts 2

Unicode typeof

parseInt

56

// Not useful, returns "object"typeof array;// Wrong, returns "object"typeof null;// Inconsistent, returns "function" or "object"typeof /a/;

// Good, returns 8 // Wrong, returns 0parseInt("08", 10); parseInt("08");

Page 57: Javascript The Good Parts

Javascript the bad parts 3

+ Floating Point

Phony Arrays

Falsy values

== type coercion

57

0.2 + 0.1 === 0.3 // false

arguments.join // returns undefined

if (book.name == null) { ... // 2 errors, works by coincidence

'' == '0' // false0 == '' // true0 == '0' // true

false == undefined // falsefalse == null // falsenull == undefined // true

Page 58: Javascript The Good Parts

Javascript the bad parts 4

Objects are not hashes

Deep for..in

Extending native prototypes kill kittens Prototype library mess

58

var cache;var word = getWord(); // returns "constructor"if (word in cache) { // ops, true

// safe wayfor (var i in list) { if (list.hasOwnProperty(i)) { // do something }}

Page 59: Javascript The Good Parts

Credits

Thank to Douglas Crockford and his book He knows the way

59