javascript the good parts v2
DESCRIPTION
Second iteration of my javascript talk. Presented at PHP Day Italia 2009 on May 15th. Slides refactored, cut down code examples and added some content about js abstractions and ecmascript 3.1. See http://federico.galassi.net/2009/05/17/javascript-the-good-parts-talk/ Follow me on Twitter! https://twitter.com/federicogalassiTRANSCRIPT
‣ The language of the Web‣ A nice, elegant, expressive
language
Why Javascript
2
‣ A nice, elegant, expressive language...‣ What??
Javascript: really a good language?
3
‣ Good for web pages‣ Bad for “serious” programming
‣ large projects‣ maintainable code
Javascript perceived as a toy language
4
‣ Stanford UniversityCS 242 “Programming Languages” 2008
‣ Mozilla Corporation‣ Firefox
‣ Many more...
Javascript is a toy language? Bullshit!!
5
‣ The Most Misunderstood language ever‣ Different from mainstream‣ Design mistakes‣ Traditionally runs in the browser
Javascript is not toy language...So what?
6
‣ Not the language of your choice‣ You already know other good languages
‣ It’s “easy”, no need to learn‣ Copy&Paste Oriented Programming
!=
Javascript is different: not your choice
7
‣ Familiar syntax from Java/C‣ Pretty exotic foundations
‣Objects from Self‣Functions from Scheme
if (x < 1) { x++;}
Javascript is different: an exotic language
8
Javascript has design mistakes
‣ Short lab time‣ hacked in one week in may 1995‣ in Netscape 2 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
‣ Inconsistent implementations‣ poor specifications
‣ Depends on DOM for I/O‣ and it sucks!
‣ Lack of common features‣ file system access‣ sockets‣ “require”
‣ No standard libraries
Javascript usually runs in the browser
10
‣ The Blooming of Abstractions
Javascript: Abstractions
11
‣ Fix the language‣ Add events portably‣ Select DOM elements easily
Javascript: Abstractions fix it
12
YAHOO.util.Event.addListener("elementid", "click", fnCallback);
$(".myclass")
Javascript: Abstractions rewrite it
‣ Rewrite the language‣ Declare a “classical” class
13
var Person = new Class({ initialize: function(name){ this.name = name; }, greet: function(){ alert("hi, i am " + this.name); }});
‣ Language??‣ It’s a Virtual Machine!
Javascript: Abstractions ignore it
14
public class StockWatcher implements EntryPoint {
private Button addStockButton = new Button("Add"); public void onModuleLoad() { // Listen for mouse events on the Add button. addStockButton.addClickHandler(new ClickHandler() { public void onClick(ClickEvent event) { addStock(); } }); }
‣ Abstractions are useful yet...‣ All non-trivial abstractions, to some degree, are
leaky.‣ Knowledge is always good
Javascript: Abstractions...beware
15
‣ Imperative‣ Functional‣ Object Oriented‣ Simple‣ Winner by natural selection
‣ ...where java failed.
DachshundEvolution
Javascript rules as it is!
16
Javascript the different good parts:Functions 1
‣ First Class Functions‣ are objects‣ can be created at runtime‣ can be stored in variables‣ can be created as anonymous literals
17
// Creation with literalvar hello = function(name) { return "hello " + name;};
// Invocationhello; // function()hello("world"); // "hello world"
Javascript the different good parts:Functions 2
‣ First Class Functions‣ can be passed as parameters
to functions‣ can be returned by functions
18
// Passed as parameter and invokedvar hey = function() { print "hey" };var twice = function(func) { func(); func();};twice(hey); // prints "heyhey"
// Returned by a functionvar makeHey = function() { return function() { return "hey”; }};var hey2 = makeHey();hey2(); // "hey"
‣ Scopes‣ Global‣ Function
‣ No block-level
Javascript the different good parts:Functions and Scope
19
function outer() {
}
function inner() {
}
g = 1
b = 2
o = 3
i = 4
Global
Function
var g = 1;
if (true) {
var b = 2;
}
var i = 4;
var o = 3;
‣ Scope Chain‣ Each scope
“inherits” fromthe “previous”one
Javascript the different good parts:Functions and Scope Chain
20
function outer() {
}
function inner() {
}
g = 1
b = 2
o = 3
i = 4
Scope Chain
Global
Function
var g = 1;
if (true) {
var b = 2;
}
var i = 4;
var o = 3;
‣ Closure:Functions“remember”their scopechain
Javascript the different good parts:Functions as Closures
21
g = 1
g = 3
Scope Chain
Global
function outer() {
var g = 3;
return
}
function() {
return g;
}
Function
var g = 1
var inner = outer();
inner(); // returns 3
‣ Containers of key/value pairs‣ keys are strings‣ values are anything
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 1
22
// 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 2‣ Objects are dynamic
‣ Properties can be added and removed at runtime‣ No class constraints
23
‣ Methods arefunction valuedproperties
‣ Inside methodsthis is bound toobject “on the left”
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 Methods
24
‣ Every object can be linked to another object through the special “prototype” property
‣ If a property does not exist in the object, request is delegated to its prototype
another_point
__proto__ -
20"x"
point
-__proto__
10
10
"x"
"y"
var point = { x: 10, y: 10};var another_point = Object.create(point);another_point.x = 20;
another_point.x; // returns 20another_point.y; // returns 10 (delegated)
Javascript the different good parts:Objects Prototype
25
‣ Delegation works for methods too‣ this is always bound to the “first object”
// 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 and Methods
26
‣ Properties are resolved by following the Prototype Chain
‣ Prototype Chains always ends with Object‣ Beyond there’s undefined
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
Javascript the different good parts:Objects Prototype Chain
27
‣ Prototypes are javascript way to share‣ Data‣ Behavior
Javascript the different good parts:Objects Prototypal Inheritance 1
28
‣ 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
Javascript the different good parts:Objects Prototypal Inheritance 2
29
‣ Ok, I cheated‣ __proto__ available in mozilla only‣ Object.create coming in next revision of language
‣ Javascript is schizophrenic‣ Prototypal nature‣ Wannabe classical
Javascript the different good parts:Objects Prototypal Inheritance 3
30
Javascript the different good parts:Object Constructor 1
‣ Constructor Functions‣ Function is a class constructor‣ Function prototype is class behavior‣ new makes new objects
‣ Why?‣ feels classical‣ feels familiar
31
function Rectangle(w, h) { this.w = w; this.h = h;}Rectangle.prototype.higher =function() { this.h += 1 };
var rect = new Rectangle(5,10);
‣ Worst of both worlds‣ Unnecessarily complicated‣ Hide prototypal nature‣ Weird for classical programmers
Javascript the different good parts:Object Constructor 2
32
‣ Fortunately there’s a Quick Fix
// create an object with a given prototype
if (typeof Object.create !== 'function') { Object.create = function (o) { var F = function() {}; F.prototype = o; return new F(); };}
var siamese = Object.create(cat);
Javascript the different good parts:Objects Constructor Functions Fix
33
‣ No real arrays in javascript‣ They’re objects in disguise
‣ special props and methods‣ Cool literal syntax
Javascript the different good parts:Arrays
34
// array literalvar numbers = [1, 2, 3];
// nice methodsnumbers.push(4); // now [1, 2, 3, 4]
// an object indeednumbers.dog = 'pretty';
Javascript the different good parts:Functional Programming
‣ Iterators‣ Callbacks‣ Module Pattern‣ Memoization
35
‣ Take control of loops‣ Reduce accidental complexity
Javascript the different good parts:Functional Programming Iterators
36
// 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
37
// 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
38
// 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
39
// 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;}, 0);// returns 55
Javascript the different good parts:Iterators Example 4
40
// 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
41
// 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
42
‣ Manage asynchronous communication‣ Hide complexity
Javascript the different good parts:Functional Programming Callbacks
43
// 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
44
// 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
45
// 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
46
‣ Hide state and behavior
Javascript the different good parts:Functional Programming Module Pattern
47
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
48
‣ Cache computation‣ Speed up execution
Javascript the different good parts:Functional Programming Memoization
49
// 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
50
// wasted computation on already calculated pixels// 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
51
‣ The features you should definitely avoid
Javascript the bad parts
52
// 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 1
‣ Global variables‣ Semicolon insertion
‣ Reserved words
53
// 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 2
‣ Unicode‣ typeof
‣ parseInt
54
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 3
‣ +‣ Floating Point
‣ Phony Arrays
‣ Falsy values
‣ == type coercion
55
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 }}
Javascript the bad parts 4
56
‣ Objects are not hashes
‣ Deep for..in
‣ Extending native prototypes kill kittens‣ new
‣ forgetting new makes global variables!
‣ ECMAScript 3.1 to Save Us‣ Object.create built-in‣ Properties enumerable/writable/configurable‣ JSON built-in‣ Properties accessors‣ Security
‣ strict mode‣ object “lock down”
‣ Coming Soon On Your Browser!
Javascript the bad parts: ES3.1 Salvation
57
‣ Thank to Douglas Crockford and his book‣ He knows the way
Credits
58