JavaScript Survival Guide
Upcoming SlideShare
Loading in...5
×
 

JavaScript Survival Guide

on

  • 6,248 views

How to stop to worry and starting to love JavaScript

How to stop to worry and starting to love JavaScript

Statistics

Views

Total Views
6,248
Views on SlideShare
5,854
Embed Views
394

Actions

Likes
26
Downloads
260
Comments
3

11 Embeds 394

http://localhost 163
http://www.codemotion.it 74
http://presentz.org 43
http://swpksi.posco.net 31
http://paper.li 31
http://2011.codemotion.it 21
http://codemotion.it 17
http://dev.presentz.org 6
https://twitter.com 4
http://www.linkedin.com 3
http://codemotion.macaronilab.com 1
More...

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

CC Attribution-NonCommercial-ShareAlike LicenseCC Attribution-NonCommercial-ShareAlike LicenseCC Attribution-NonCommercial-ShareAlike License

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

JavaScript Survival Guide JavaScript Survival Guide Presentation Transcript

  • JavaScript Survival GuideGiordano Scalzo
  • I’m not a guru!
  • I’m still learning
  • Java/C++ Background
  • Why?
  • JavaScript isn’t this anymore
  • JavaScript is everywhere!
  • JavaScript is trendy!Technology Radar
  • JavaScript is trendy!Technology Radar
  • Hacked by Brendan Eich in one week...
  • Former Mocha, then LiveScript,renamed to JavaScript by Netscape.
  • Now ECMAScript.
  • At the beginning...
  • after a while...
  • and...
  • :-(
  • and so...
  • Back to study!
  • Started a notebook...
  • Essential Scope
  • function sum(x, y){ // implied global result = x + y; return result; }{antipattern}
  • Global variables are evil!
  • Variables clash
  • Always declare variables with var function sum(x, y){ var result = x + y; return result; }{pattern}
  • function foo(){ var a = b = 0; //... }{antipattern}
  • b become global function foo(){ var a = (b = 0); //... }{antipattern}
  • don’t use assign chain in definition function foo(){ var a, b; a = b = 0; //... }{pattern}
  • Single var pattern function func(){ var a = 1, b = 2, sum = a + b, myobject = {}, i, j; // function body... }{pattern}
  • Don’t forget comma otherwise...
  • ... variables become globals
  • Hoisting myname = "global"; // global variable function func(){ // code... console.log(myname); // "undefined" // code... var myname = "local"; console.log(myname); // "local" } func();{antipattern}
  • Hoisting myname = "global"; // global variable function func(){ var myname = "declared"; // code... console.log(myname); // "declared" // code... myname = "local"; console.log(myname); // "local" } func();{pattern}
  • Against minimum vertical distance principle“Variables should be declared as close totheir usage as possible” Robert C. Martin - Clean Code
  • EssentialLiteral and Constructor
  • In JavaScript almost everything is an object
  • It’s easy...var person = new Object();person.name = "Scott";person.say = function(){ return "I am " + this.name;};console.log(person.say());
  • but wrong! :-( var person = new Object(); person.name = "Scott"; person.say = function(){ return "I am " + this.name; }; console.log(person.say());{antipattern}
  • var person = {}; person.name = "Scott"; person.say = function(){ return "I am " + this.name; }; console.log(person.say());{pattern}
  • What if we need similar objects... var person = {}; person.name = "Scott"; person.say = function(){ return "I am " + this.name; }; console.log(person.say()); // I am Scott var otherPerson = {}; otherPerson.name = "Tiger"; otherPerson.say = function(){ return "I am " + this.name; }; console.log(otherPerson.say()); // I am Tiger
  • A lot of duplication var person = {}; person.name = "Scott"; person.say = function(){ return "I am " + this.name; }; console.log(person.say()); // I am Scott var otherPerson = {}; otherPerson.name = "Tiger"; otherPerson.say = function(){ return "I am " + this.name; }; console.log(otherPerson.say()); // I am Tiger
  • Duplication is evil!
  • Custom Constructor Functions var Person = function(name){ this.name = name; this.say = function(){ return "I am " + this.name; } } var person = new Person("Scott"); console.log(person.say()); // I am Scott{pattern}
  • Behind the scenes... var Person = function(name){ // var this = {}; this.name = name; this.say = function(){ return "I am " + this.name; }; // return this; };{pattern}
  • So, at the end... var Person = function(name){ this.name = name; this.say = function(){ return "I am " + this.name; }; }; var scott = new Person(Scott); var tiger = new Person(Tiger); console.log(scott.say()); console.log(tiger.say());{pattern}
  • What if we forget new?
  • this will point to global objectvar Person = function(name){ this.name = name; this.say = function(){ return "I am " + this.name; };};var scott = new Person(Scott)var adam = Person(Adam)console.log(typeof scott); //objectconsole.log(scott.name); // Scottconsole.log(typeof adam); //undefinedconsole.log(window.name); // Adam
  • Enforce new pattern one: naming convention
  • var Person = function(name){ var that = {}; that.name = name; that.say = function(){ return "I am " + that.name;}; return that; }; var scott = new Person(Scott) var adam = Person(Adam) console.log(typeof scott); //Object console.log(scott.name); // Scott console.log(typeof adam); //Object console.log(adam.name); // Adam{pattern}
  • Drawback: we loose prototype reference :-( var Person = function(name){ var that = {}; that.name = name; that.say = function(){ return "I am " + that.name; }; return that; }; Person.prototype.iamhumanbeing = true; var scott = new Person(Scott) var adam = Person(Adam) console.log(scott.iamhumanbeing); // undefined console.log(adam.iamhumanbeing); // undefined
  • Interm!zo Prototype property
  • Define ancestors chainvar foo = {one: 1, two: 2};var bar = {three: 3};foo.__proto__ = bar;console.log(foo.one);console.log(foo.three);
  • bar three: 3 foo one: 1 two: 2__proto__
  • Behind the scenes...var Person = function(name){ // this.prototype = {constructor: this} var that = {}; that.name = name; that.say = function(){ return "I am " + that.name; }; return that;};
  • Self invoking constructor var Person = function(name){ if (this instanceof Person) { this.name = name; this.say = function(){ return "I am " + that.name; } } else { return new Person(name); } }; Person.prototype.iamhumanbeing = true; var scott = new Person(Scott) var adam = Person(Adam) console.log(scott.name); // Scott console.log(adam.name); // Adam console.log(scott.iamhumanbeing); // true console.log(adam.iamhumanbeing); // true{pattern}
  • Essential Functions
  • Functions as first class objects
  • Immediate functions (function(){ alert(watch out!); })();
  • Initialization pattern (function(){ var days = [Sun, Mon, Tue, Wed, Thu, Fri, Sat], today = new Date(), msg = Today is + days[today.getDay()] + , + today.getDate(); console.log(msg); })(); // "Today is Wed, 10"{pattern}
  • Function scope
  • 5 globals... // constructors function Parent(){ } function Child(){ } // a variable var some_var = 1; // some objects var module1 = {}; module1.data = { a: 1, b: 2 }; var module2 = {};{antipattern}
  • 1 global!// global objectvar MYAPP = (function(){ var my = {}; {pattern} // constructors my.Parent = function(){}; my.Child = function(){}; // a variable my.some_var = 1; // an object container my.modules = {}; // nested objects my.modules.module1 = {}; my.modules.module1.data = { a: 1, b: 2 }; my.modules.module2 = {}; return my;})();console.log(MYAPP.modules.module1.data.a); // 1
  • What about encapsulation?
  • function Gadget(){ this.name = iPod; this.stretch = function(){ return iPad; } }; var toy = new Gadget(); console.log(toy.name); // `iPod` toy.name = Zune console.log(toy.name); // `Zune` is public console.log(toy.stretch()); // stretch() is public{antipattern}
  • Create private member function Gadget(){ var name = iPod; this.getName = function(){ return name; } }; var toy = new Gadget(); console.log(toy.getName()); // `iPod` toy.name = Zune console.log(toy.getName()); // `iPod`{pattern}
  • for methods too function Gadget() { var name = iPod; var upgrade = function(){ return iPhone; } this.getName = function () { return name; } this.pay = function() { return upgrade(); } }; var toy = new Gadget(); console.log(toy.pay()); // `iPhone` console.log(toy.upgrade()); // `error`{pattern}
  • Advanced Code reuse patterns
  • Classical vs prototypal inheritance vs
  • Classical inheritancefunction Parent(name){ this.name = name;};Parent.prototype.say = function(){ return My name is + this.name;};function Child(name){ this.name = name;};inherit(Child, Parent);var dad = new Parent(Larry);var kid = new Child(Scott);console.log(dad.say()); // My name is Larryconsole.log(kid.say()); // My name is Scott
  • function(){ return My name is + this.name; }; Parent.prototype say()new Parent() name: Larry __proto__ console.log(dad.say());
  • Default Classical Inheritance pattern function inherit(C, P) { C.prototype = new P(); };
  • function(){ return My name is + this.name; }; Parent.prototype say() new Parent() new Child() name: Larry name: Scott __proto__ __proto__console.log(kid.say());
  • Drawback: it doesn’t call parent constructor function Parent(name){ this.name = name; }; Parent.prototype.say = function(){ return My name is + this.name; }; function Child(name){ this.name = name; }; inherit(Child, Parent); var dad = new Parent(Larry); var kid = new Child(Scott); console.log(dad.say()); // My name is Larry console.log(kid.say()); // My name is Scott
  • Drawback: it doesn’t call parent constructor function Parent(name){ this.name = name; }; Parent.prototype.say = function(){ return My name is + this.name; }; function Child(name){ }; function inherit(C, P) { C.prototype = new P(); }; inherit(Child, Parent); var kid = new Child(Scott); console.log(kid.say()); // My name is undefined
  • Pattern Extension: rent a constructor function Child(name){ Parent.apply(this, arguments); };
  • Pattern Extension: rent a constructorfunction Parent(name){ this.name = name;};Parent.prototype.say = function(){ return My name is + this.name;};function Child(name){ Parent.apply(this, arguments);};function inherit(C, P){ C.prototype = new P();};inherit(Child, Parent);var dad = new Parent(Larry);var kid = new Child(Scott);console.log(dad.say()); // My name is Larryconsole.log(kid.say()); // My name is Scott
  • Drawback: parent constructor is called twice function Parent(name){ this.name = name; }; Parent.prototype.say = function(){ return My name is + this.name; }; function Child(name){ Parent.apply(this, arguments); }; function inherit(C, P){ C.prototype = new P(); }; inherit(Child, Parent); var dad = new Parent(Larry); var kid = new Child(Scott); console.log(dad.say()); // My name is Larry console.log(kid.say()); // My name is Scott
  • Drawback: parent constructor is called twice function Parent(name){ this.name = name; }; Parent.prototype.say = function(){ return My name is + this.name; }; function Child(name){ Parent.apply(this, arguments); }; function inherit(C, P){ C.prototype = new P(); }; inherit(Child, Parent); var dad = new Parent(Larry); var kid = new Child(Scott); console.log(dad.say()); // My name is Larry console.log(kid.say()); // My name is Scott
  • Drawback: parent constructor is called twice function Parent(name){ this.name = name; }; Parent.prototype.say = function(){ return My name is + this.name; }; function Child(name){ Parent.apply(this, arguments); }; function inherit(C, P){ C.prototype = new P(); }; inherit(Child, Parent); var dad = new Parent(Larry); var kid = new Child(Scott); console.log(dad.say()); // My name is Larry console.log(kid.say()); // My name is Scott
  • mmmm let’s try with the same prototype
  • Share the same prototypefunction inherit(C, P){ C.prototype = P.prototype;};
  • Parent.prototype say()new Child() new Parent()name: Scott name: Larry__proto__ __proto__
  • Share the same prototypeInheritance works as expectedConstructor called only onceLow memory footprint
  • Share the same prototypeChild objects can affect other objects
  • Enhance the pattern: temporary constructor function inherit(C, P) { var F = function () {}; F.prototype = P.prototype; C.prototype = new F(); };
  • Parent.prototype say()new Parent() new F() name: Larry __proto__ __proto__ new Child() name: Scott __proto__
  • The Holy Grail Pattern of classical inheritance function inherit(C, P) { var F = function () {}; F.prototype = P.prototype; C.prototype = new F(); C.uber = P.prototype; C.prototype.constructor = C; };
  • We got it!
  • What about Prototypal Inheritance?
  • No more classes, only objects
  • What we want in prototypal inheritance var parent = { name: "Larry", say: function(){ return "My name is " + this.name; } }; var child = object(parent); child.name = Scott console.log(child.say()); // "Scott"
  • Prototypal inheritance function function object(o) { function F() {} F.prototype = o; return new F(); };
  • parentname: Scott say() child = new F() name: Larry __proto__
  • With constructor functionvar Parent = function(name){ this.name = name; this.say = function(){ return "My name is " + this.name; }};var child = object(new Parent("Larry"));child.name = Scottconsole.log(child.say()); // "Scott"
  • better classical or prototypal?
  • It depends
  • Goals of inheritance is reuse and reduce duplication
  • isA relationship... Liskov principle...difficult to tame inheritance...
  • A modern and better approach is to use Mix-In
  • A beahviour...var Serializer = function () {};Serializer.prototype = { serialize: function () { var output = []; for (key in this) { // append this[key] to output // ... } return output.join(, ); }};
  • another beahviour...var XmlBuilder = function () {};XmlBuilder.prototype = { toXml: function () { var output = ; for (key in this) { // append xml of this[key] to output // ... } return output; }};
  • and an object...var Author = function (name, books) { this.name = name || ""; this.books = books || [];}
  • result!augment(Author, Serializer);augment(Author, XmlBuilder);var author = new Author(Umberto Eco, [Il nome della rosa, Il Pendolo di Foucault]);var serializedString = author.serialize();console.log(serializedString); // name: Umberto Eco, // books: Il nome della rosa, // Il Pendolo di Foucaultvar xmlString = author.toXml();console.log(xmlString); //<name>Umberto Eco</name> // <book>Il nome della rosa</book> // <book>Il Pendolo di Focault</book>
  • The recipefunction augment(receivingClass, givingClass) { for (methodName in givingClass.prototype) { if (!receivingClass.prototype[methodName]) { receivingClass.prototype[methodName] = givingClass.prototype[methodName]; } }}
  • Advanced Browser Patterns
  • JavaScript still live into browser...
  • Dom access: write for (var i = 0; i < 100; i += 1) { document.getElementById("result").innerHTML += i + ", "; }{antipattern}
  • Dom access: update local variable var i, content = ""; for (i = 0; i < 100; i += 1) { content += i + ","; } document.getElementById("result").innerHTML += content;{pattern}
  • Dom access: readvar padding = document.getElementById("result").style.padding, margin = document.getElementById("result").style.margin;{antipattern}
  • Dom access: read with local variable var style = document.getElementById("result").style, padding = style.padding, margin = style.margin;{pattern}
  • Dom manipulation // appending nodes as they are created var p, t; p = document.createElement(p); t = document.createTextNode(first paragraph); p.appendChild(t); document.body.appendChild(p); p = document.createElement(p); t = document.createTextNode(second paragraph); p.appendChild(t); document.body.appendChild(p);{antipattern}
  • Dom manipulation var p, t, frag; frag = document.createDocumentFragment(); p = document.createElement(p); t = document.createTextNode(first paragraph); p.appendChild(t); frag.appendChild(p); p = document.createElement(p); t = document.createTextNode(second paragraph); p.appendChild(t); frag.appendChild(p); document.body.appendChild(frag);{pattern}
  • The place of <script> element <!doctype html> <html> <head> <title>My App</title> <script src="jquery.js"></script> <script src="jquery.quickselect.js"></script> <script src="jquery.lightbox.js"></script> <script src="myapp.js"></script> </head> <body> ... </body> </html>Worst{antipattern}
  • The place of <script> element <!doctype html> <html> <head> <title>My App</title> <script src="all_20110127.js"></script> </head> <body> ... </body> </html>{antipattern}
  • The place of <script> element <!doctype html> <html> <head> <title>My App</title> </head> <body> ... <script src="all_20110127.js"></script> </body> </html>{pattern}
  • It’s just a beginning...
  • peep code
  • Study
  • “Save it for a rainy day!”
  • Check your code with jslint.com
  • http://jashkenas.github.com/coffee-script/
  • http://jashkenas.github.com/coffee-script/ It’s just JavaScript!
  • # Assignment: var cubes, math, num, number, opposite,number = 42 race, square;opposite = true var __slice = Array.prototype.slice; number = 42; opposite = true;# Conditions: if (opposite) {number = -42 if opposite number = -42; }# Functions: square = function(x) {square = (x) -> x * x return x * x; };# Objects:math = math = { root: Math.sqrt root: Math.sqrt, square: square square: square, cube: (x) -> x * square x cube: function(x) { return x * square(x); } }; race = function() {# Splats: var runners, winner;race = (winner, runners...) -> winner = arguments[0], runners = 2 print winner, runners <= arguments.length ? __slice.call(arguments, 1) : []; return print(winner, runners); };} JavaScript
  • # Assignment: var cubes, math, num, number, opposite,number = 42 race, square;opposite = true var __slice = Array.prototype.slice; number = 42; opposite = true;# Conditions: if (opposite) {number = -42 if opposite number = -42; }# Functions: square = function(x) {square = (x) -> x * x return x * x; };# Objects:math = math = { root: Math.sqrt root: Math.sqrt, square: square square: square, cube: (x) -> x * square x cube: function(x) { return x * square(x); } }; race = function() {# Splats: var runners, winner;race = (winner, runners...) -> winner = arguments[0], runners = 2 print winner, runners <= arguments.length ? __slice.call(arguments, 1) : []; return print(winner, runners); };} JavaScript
  • # Assignment: var cubes, math, num, number, opposite,number = 42 race, square;opposite = true var __slice = Array.prototype.slice; number = 42; opposite = true;# Conditions: if (opposite) {number = -42 if opposite number = -42; }# Functions: square = function(x) {square = (x) -> x * x return x * x; };# Objects:math = math = { root: Math.sqrt root: Math.sqrt, square: square square: square, cube: (x) -> x * square x cube: function(x) { return x * square(x); } }; race = function() {# Splats: var runners, winner;race = (winner, runners...) -> winner = arguments[0], runners = 2 print winner, runners <= arguments.length ? __slice.call(arguments, 1) : []; return print(winner, runners); };} JavaScript
  • # Assignment: var cubes, math, num, number, opposite,number = 42 race, square;opposite = true var __slice = Array.prototype.slice; number = 42; opposite = true;# Conditions: if (opposite) {number = -42 if opposite number = -42; }# Functions: square = function(x) {square = (x) -> x * x return x * x; };# Objects:math = math = { root: Math.sqrt root: Math.sqrt, square: square square: square, cube: (x) -> x * square x cube: function(x) { return x * square(x); } }; race = function() {# Splats: var runners, winner;race = (winner, runners...) -> winner = arguments[0], runners = 2 print winner, runners <= arguments.length ? __slice.call(arguments, 1) : []; return print(winner, runners); };} JavaScript
  • # Assignment: var cubes, math, num, number, opposite,number = 42 race, square;opposite = true var __slice = Array.prototype.slice; number = 42; opposite = true;# Conditions: if (opposite) {number = -42 if opposite number = -42; }# Functions: square = function(x) {square = (x) -> x * x return x * x; };# Objects:math = math = { root: Math.sqrt root: Math.sqrt, square: square square: square, cube: (x) -> x * square x cube: function(x) { return x * square(x); } }; race = function() {# Splats: var runners, winner;race = (winner, runners...) -> winner = arguments[0], runners = 2 print winner, runners <= arguments.length ? __slice.call(arguments, 1) : []; return print(winner, runners); };} JavaScript
  • # Assignment: var cubes, math, num, number, opposite,number = 42 race, square;opposite = true var __slice = Array.prototype.slice; number = 42; opposite = true;# Conditions: if (opposite) {number = -42 if opposite number = -42; }# Functions: square = function(x) {square = (x) -> x * x return x * x; };# Objects:math = math = { root: Math.sqrt root: Math.sqrt, square: square square: square, cube: (x) -> x * square x cube: function(x) { return x * square(x); } }; race = function() {# Splats: var runners, winner;race = (winner, runners...) -> winner = arguments[0], runners = 2 print winner, runners <= arguments.length ? __slice.call(arguments, 1) : []; return print(winner, runners); };} JavaScript
  • # Existence: if (typeof elvis != "undefined" && elvis !== null) {alert "I knew it!" if elvis? alert("I knew it!"); }# Array comprehensions: cubes = (function() {cubes = (math.cube num for num in list) var _i, _len, _results; _results = []; for (_i = 0, _len = list.length; _i < _len; _i++) { num = list[_i]; _results.push(math.cube(num)); } return _results; })(); JavaScript
  • # Existence: if (typeof elvis != "undefined" && elvis !== null) {alert "I knew it!" if elvis? alert("I knew it!"); }# Array comprehensions: cubes = (function() {cubes = (math.cube num for num in list) var _i, _len, _results; _results = []; for (_i = 0, _len = list.length; _i < _len; _i++) { num = list[_i]; _results.push(math.cube(num)); } return _results; })(); JavaScript
  • ...but it’s just another story...
  • giordano.scalzo@cleancode.it@giordanoscalzowww.slideshare.net/giordanogithub.com/gscalzo