javascript the good parts
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/federicogalassiTRANSCRIPT
Why Javascript
The language of the Web A nice, elegant, expressive
language
2
Why Javascript
A nice, elegant, expressive language... What??
3
Javascript perceived as a toy language
Good for small quick web hacks Not good for “serious” programming
large projects mantainable code
4
Javascript is a toy language? Bullshit!!
Stanford UniversityCS 242 “Programming Languages” 2008
Mozilla Corporation Firefox
Many more...
5
Javascript is not toy language...So what?
The Most Misunderstood language ever Different from mainstream Design mistakes Traditionally runs in the browser
6
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
!=
Javascript is different
Hidden nature Familiar syntax from Java/C Pretty exotic foundations
Objects from Self Functions from Scheme
8
if (x < 1) { x++;}
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
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
Javascript rules indeed!
Imperative Functional Object Oriented Simple Winner by natural selection
...where java failed.
11
DachshundEvolution
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
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
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");
// 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
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;
}
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
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
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" }}
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
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 =
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)
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
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
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
// 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
Javascript the different good parts:Objects Prototypal Inheritance 1 Prototypes are javascript way to share
Data Behaviour
27
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
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
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
// 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
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);
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(); };}
Javascript the different good parts:Arrays No real arrays in javascript They’re objects in disguise
special props and methods Cool literal syntax
34
// 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
// 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
Javascript the different good parts:Functional Programming Iterators Callbacks Module Pattern Curry Memoization
37
Javascript the different good parts:Functional Programming Iterators Take control of loops Reduce accidental complexity
38
// 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
// 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
// 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
// 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
// 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
// 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
Javascript the different good parts:Functional Programming Callbacks Manage asynchronous communication Hide complexity
45
// 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
// 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
// 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
Javascript the different good parts:Functional Programming Module Pattern Hide state and behaviour
49
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
Javascript the different good parts:Functional Programming Memoization Cache computation Speed up execution
51
// 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
// 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
Javascript the bad parts
The features you should definitely avoid
54
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" } }
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");
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
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 }}
Credits
Thank to Douglas Crockford and his book He knows the way
59