JavaScript Survival Guide

  • 5,817 views
Uploaded on

How to stop to worry and starting to love JavaScript

How to stop to worry and starting to love JavaScript

More in: Technology , Business
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
No Downloads

Views

Total Views
5,817
On Slideshare
0
From Embeds
0
Number of Embeds
4

Actions

Shares
Downloads
268
Comments
3
Likes
26

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. JavaScript Survival GuideGiordano Scalzo
  • 2. I’m not a guru!
  • 3. I’m still learning
  • 4. Java/C++ Background
  • 5. Why?
  • 6. JavaScript isn’t this anymore
  • 7. JavaScript is everywhere!
  • 8. JavaScript is trendy!Technology Radar
  • 9. JavaScript is trendy!Technology Radar
  • 10. Hacked by Brendan Eich in one week...
  • 11. Former Mocha, then LiveScript,renamed to JavaScript by Netscape.
  • 12. Now ECMAScript.
  • 13. At the beginning...
  • 14. after a while...
  • 15. and...
  • 16. :-(
  • 17. and so...
  • 18. Back to study!
  • 19. Started a notebook...
  • 20. Essential Scope
  • 21. function sum(x, y){ // implied global result = x + y; return result; }{antipattern}
  • 22. Global variables are evil!
  • 23. Variables clash
  • 24. Always declare variables with var function sum(x, y){ var result = x + y; return result; }{pattern}
  • 25. function foo(){ var a = b = 0; //... }{antipattern}
  • 26. b become global function foo(){ var a = (b = 0); //... }{antipattern}
  • 27. don’t use assign chain in definition function foo(){ var a, b; a = b = 0; //... }{pattern}
  • 28. Single var pattern function func(){ var a = 1, b = 2, sum = a + b, myobject = {}, i, j; // function body... }{pattern}
  • 29. Don’t forget comma otherwise...
  • 30. ... variables become globals
  • 31. Hoisting myname = "global"; // global variable function func(){ // code... console.log(myname); // "undefined" // code... var myname = "local"; console.log(myname); // "local" } func();{antipattern}
  • 32. Hoisting myname = "global"; // global variable function func(){ var myname = "declared"; // code... console.log(myname); // "declared" // code... myname = "local"; console.log(myname); // "local" } func();{pattern}
  • 33. Against minimum vertical distance principle“Variables should be declared as close totheir usage as possible” Robert C. Martin - Clean Code
  • 34. EssentialLiteral and Constructor
  • 35. In JavaScript almost everything is an object
  • 36. It’s easy...var person = new Object();person.name = "Scott";person.say = function(){ return "I am " + this.name;};console.log(person.say());
  • 37. but wrong! :-( var person = new Object(); person.name = "Scott"; person.say = function(){ return "I am " + this.name; }; console.log(person.say());{antipattern}
  • 38. var person = {}; person.name = "Scott"; person.say = function(){ return "I am " + this.name; }; console.log(person.say());{pattern}
  • 39. 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
  • 40. 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
  • 41. Duplication is evil!
  • 42. 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}
  • 43. Behind the scenes... var Person = function(name){ // var this = {}; this.name = name; this.say = function(){ return "I am " + this.name; }; // return this; };{pattern}
  • 44. 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}
  • 45. What if we forget new?
  • 46. 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
  • 47. Enforce new pattern one: naming convention
  • 48. 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}
  • 49. 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
  • 50. Interm!zo Prototype property
  • 51. Define ancestors chainvar foo = {one: 1, two: 2};var bar = {three: 3};foo.__proto__ = bar;console.log(foo.one);console.log(foo.three);
  • 52. bar three: 3 foo one: 1 two: 2__proto__
  • 53. 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;};
  • 54. 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}
  • 55. Essential Functions
  • 56. Functions as first class objects
  • 57. Immediate functions (function(){ alert(watch out!); })();
  • 58. 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}
  • 59. Function scope
  • 60. 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}
  • 61. 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
  • 62. What about encapsulation?
  • 63. 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}
  • 64. 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}
  • 65. 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}
  • 66. Advanced Code reuse patterns
  • 67. Classical vs prototypal inheritance vs
  • 68. 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
  • 69. function(){ return My name is + this.name; }; Parent.prototype say()new Parent() name: Larry __proto__ console.log(dad.say());
  • 70. Default Classical Inheritance pattern function inherit(C, P) { C.prototype = new P(); };
  • 71. function(){ return My name is + this.name; }; Parent.prototype say() new Parent() new Child() name: Larry name: Scott __proto__ __proto__console.log(kid.say());
  • 72. 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
  • 73. 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
  • 74. Pattern Extension: rent a constructor function Child(name){ Parent.apply(this, arguments); };
  • 75. 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
  • 76. 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
  • 77. 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
  • 78. 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
  • 79. mmmm let’s try with the same prototype
  • 80. Share the same prototypefunction inherit(C, P){ C.prototype = P.prototype;};
  • 81. Parent.prototype say()new Child() new Parent()name: Scott name: Larry__proto__ __proto__
  • 82. Share the same prototypeInheritance works as expectedConstructor called only onceLow memory footprint
  • 83. Share the same prototypeChild objects can affect other objects
  • 84. Enhance the pattern: temporary constructor function inherit(C, P) { var F = function () {}; F.prototype = P.prototype; C.prototype = new F(); };
  • 85. Parent.prototype say()new Parent() new F() name: Larry __proto__ __proto__ new Child() name: Scott __proto__
  • 86. 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; };
  • 87. We got it!
  • 88. What about Prototypal Inheritance?
  • 89. No more classes, only objects
  • 90. 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"
  • 91. Prototypal inheritance function function object(o) { function F() {} F.prototype = o; return new F(); };
  • 92. parentname: Scott say() child = new F() name: Larry __proto__
  • 93. 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"
  • 94. better classical or prototypal?
  • 95. It depends
  • 96. Goals of inheritance is reuse and reduce duplication
  • 97. isA relationship... Liskov principle...difficult to tame inheritance...
  • 98. A modern and better approach is to use Mix-In
  • 99. A beahviour...var Serializer = function () {};Serializer.prototype = { serialize: function () { var output = []; for (key in this) { // append this[key] to output // ... } return output.join(, ); }};
  • 100. another beahviour...var XmlBuilder = function () {};XmlBuilder.prototype = { toXml: function () { var output = ; for (key in this) { // append xml of this[key] to output // ... } return output; }};
  • 101. and an object...var Author = function (name, books) { this.name = name || ""; this.books = books || [];}
  • 102. 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>
  • 103. The recipefunction augment(receivingClass, givingClass) { for (methodName in givingClass.prototype) { if (!receivingClass.prototype[methodName]) { receivingClass.prototype[methodName] = givingClass.prototype[methodName]; } }}
  • 104. Advanced Browser Patterns
  • 105. JavaScript still live into browser...
  • 106. Dom access: write for (var i = 0; i < 100; i += 1) { document.getElementById("result").innerHTML += i + ", "; }{antipattern}
  • 107. Dom access: update local variable var i, content = ""; for (i = 0; i < 100; i += 1) { content += i + ","; } document.getElementById("result").innerHTML += content;{pattern}
  • 108. Dom access: readvar padding = document.getElementById("result").style.padding, margin = document.getElementById("result").style.margin;{antipattern}
  • 109. Dom access: read with local variable var style = document.getElementById("result").style, padding = style.padding, margin = style.margin;{pattern}
  • 110. 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}
  • 111. 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}
  • 112. 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}
  • 113. The place of <script> element <!doctype html> <html> <head> <title>My App</title> <script src="all_20110127.js"></script> </head> <body> ... </body> </html>{antipattern}
  • 114. The place of <script> element <!doctype html> <html> <head> <title>My App</title> </head> <body> ... <script src="all_20110127.js"></script> </body> </html>{pattern}
  • 115. It’s just a beginning...
  • 116. peep code
  • 117. Study
  • 118. “Save it for a rainy day!”
  • 119. Check your code with jslint.com
  • 120. http://jashkenas.github.com/coffee-script/
  • 121. http://jashkenas.github.com/coffee-script/ It’s just JavaScript!
  • 122. # 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
  • 123. # 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
  • 124. # 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
  • 125. # 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
  • 126. # 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
  • 127. # 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
  • 128. # 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
  • 129. # 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
  • 130. ...but it’s just another story...
  • 131. giordano.scalzo@cleancode.it@giordanoscalzowww.slideshare.net/giordanogithub.com/gscalzo