SlideShare a Scribd company logo
1 of 143
Download to read offline
JavaScript Survival Guide




                    Roma,
Giordano Scalzo     5 marzo 2011
I’m not a guru!
I’m still learning
Java/C++ guy in the past
Ruby/ObjectiveC guy in the present
Why to learn JavaScript?
JavaScript isn’t this anymore
JavaScript is everywhere!
JavaScript is popular!
JavaScript is trendy!

Technology Radar
JavaScript is trendy!

Technology Radar
It should be easy...
Hacked by Brendan Eich in one week...
At the beginning...
after a while...
traps everywhere..
traps everywhere..
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}
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(){
    	 // code...
        console.log(myname); // "undefined"

        // code...
        var myname = "local";
        console.log(myname); // "local"
    }

    func();




{antipattern}
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 to
their usage as possible”
          Robert C. Martin - Clean Code
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
Essential
Literal 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.prototype = {constructor: 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 object

var 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); //object
console.log(scott.name); // Scott
console.log(typeof adam); //'undefined'
console.log(window.name); // Adam
this will point to global object

var 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); //object
console.log(scott.name); // Scott
console.log(typeof adam); //'undefined'
console.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}
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
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 chain



  var foo = {one: 1, two: 2};
  var bar = {three: 3};
  foo.__proto__ = bar;
  console.log(foo.one);
  console.log(foo.three);
Define ancestors chain



  var foo = {one: 1, two: 2};
  var bar = {three: 3};
  foo.__proto__ = bar;
  console.log(foo.one);
  console.log(foo.three);
console.log(foo.one);
                          bar
                        three: 3



        foo
       one: 1
        two: 2
    __proto__
console.log(foo.one);
                          bar
                        three: 3



        foo
       one: 1
        two: 2
    __proto__
console.log(foo.three);
                            bar
                          three: 3



         foo
        one: 1
        two: 2
     __proto__
console.log(foo.three);
                            bar
                          three: 3



         foo
        one: 1
        two: 2
     __proto__
console.log(foo.three);
                            bar
                          three: 3



         foo
        one: 1
        two: 2
     __proto__
End
Interm!zo
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}
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}
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}
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 object
var MYAPP = (function(){
                                  {pattern}
    var my = {};
    // 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
1 global!
// global object
var MYAPP = (function(){
                                  {pattern}
    var my = {};
    // 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}
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}
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}
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
  Test Framework
JavaScript is madly in love with Testing.
JavaScript is madly in love with Testing.




                              JSUnit
JavaScript is madly in love with Testing.




                              JSUnit




                  JSTest
JavaScript is madly in love with Testing.




 QUnit                        JSUnit




                  JSTest
JavaScript is madly in love with Testing.




 QUnit                        JSUnit




                              Vows
                  JSTest
JavaScript is madly in love with Testing.




 QUnit                        JSUnit




jsUnitTest                    Vows
                  JSTest
JavaScript is madly in love with Testing.

                           Blue Ridge

 QUnit                        JSUnit




jsUnitTest                    Vows
                  JSTest
JavaScript is madly in love with Testing.

    Screw unit             Blue Ridge

 QUnit                        JSUnit




jsUnitTest                    Vows
                  JSTest
JavaScript is madly in love with Testing.

    Screw unit             Blue Ridge

 QUnit                        JSUnit


                             YUI Test

jsUnitTest                    Vows
                  JSTest
JavaScript is madly in love with Testing.

    Screw unit             Blue Ridge
                JSpec
 QUnit                        JSUnit


                             YUI Test

jsUnitTest                    Vows
                  JSTest
JavaScript is madly in love with Testing.

    Screw unit             Blue Ridge
                JSpec
 QUnit                        JSUnit

 Unitesting
                             YUI Test

jsUnitTest                    Vows
                  JSTest
JavaScript is madly in love with Testing.

    Screw unit             Blue Ridge
                JSpec
 QUnit                        JSUnit

 Unitesting    Jasmine
                             YUI Test

jsUnitTest                    Vows
                  JSTest
JavaScript is madly in love with Testing.


         http://pivotal.github.com/jasmine/
Jasmine: BDD RSpec-like syntax
describe('Array', function() {
  var array;

  describe('#unique', function() {
    beforeEach(function() {
      array = [3,3,4];
    });

    it("returns only the unique values in the array",
function() {
      expect(array.unique()).toEqual([3,4]);
    });
  });
});
Not mocks and Stubs


Spies
Jasmine: Spies as Mocks

function BetterArray(array){
    this.array = array;
}

BetterArray.prototype = {
    joinify: function(){

         // Does some cool stuff

         this.array = this.array.join('.');
    }
}
Jasmine: Spies as Mocks
describe('BetterArray', function() {
  var betterArray, anArray = [3,3,4];

  beforeEach(function() {
    betterArray = new BetterArray(anArray);
  });

  describe('#joinify', function() {
    it("calls the standard join method on Array",
function() {
      var joinSpy = spyOn(betterArray.array, 'join');
      betterArray.joinify();
      expect(joinSpy).toHaveBeenCalled();
    });
  });
});
Jasmine: Spies as Mocks
describe('BetterArray', function() {
  var betterArray, anArray = [3,3,4];

  beforeEach(function() {
    betterArray = new BetterArray(anArray);
  });

  describe('#joinify', function() {
    it("calls the standard join method on Array",
function() {
      var joinSpy = spyOn(betterArray.array, 'join');
      betterArray.joinify();
      expect(joinSpy).toHaveBeenCalled();
    });
  });
});
Jasmine: Spies as Mocks
describe('BetterArray', function() {
  var betterArray, anArray = [3,3,4];

  beforeEach(function() {
    betterArray = new BetterArray(anArray);
  });

  describe('#joinify', function() {
    it("calls the standard join method on Array",
function() {
      var joinSpy = spyOn(betterArray.array, 'join');
      betterArray.joinify();
      expect(joinSpy).toHaveBeenCalled();
    });
  });
});
Jasmine: Spies as Mocks
describe('BetterArray', function() {
  var betterArray, anArray = [3,3,4];

  beforeEach(function() {
    betterArray = new BetterArray(anArray);
  });

  describe('#joinify', function() {
    it("calls the standard join method on Array",
function() {
      var joinSpy = spyOn(betterArray.array, 'join');
      betterArray.joinify();
      expect(joinSpy).toHaveBeenCalled();
    });
  });
});
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: read




var 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


   // 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}
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}
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}
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...
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
                    @giordanoscalzo
                     www.slideshare.net/giordano
                    github.com/gscalzo

                                         Roma,5 marzo 2011


http://creativecommons.org/licenses/by-nc-sa/3.0/

More Related Content

What's hot

JavaScript - new features in ECMAScript 6
JavaScript - new features in ECMAScript 6JavaScript - new features in ECMAScript 6
JavaScript - new features in ECMAScript 6
Solution4Future
 
Rust-lang
Rust-langRust-lang
The mighty js_function
The mighty js_functionThe mighty js_function
The mighty js_function
timotheeg
 

What's hot (19)

ES2015 (ES6) Overview
ES2015 (ES6) OverviewES2015 (ES6) Overview
ES2015 (ES6) Overview
 
ES6 - Next Generation Javascript
ES6 - Next Generation JavascriptES6 - Next Generation Javascript
ES6 - Next Generation Javascript
 
An Intro To ES6
An Intro To ES6An Intro To ES6
An Intro To ES6
 
JavaScript - new features in ECMAScript 6
JavaScript - new features in ECMAScript 6JavaScript - new features in ECMAScript 6
JavaScript - new features in ECMAScript 6
 
ECMAScript 6
ECMAScript 6ECMAScript 6
ECMAScript 6
 
Rust-lang
Rust-langRust-lang
Rust-lang
 
Антон Нонко, Классические строки в C++
Антон Нонко, Классические строки в C++Антон Нонко, Классические строки в C++
Антон Нонко, Классические строки в C++
 
Explaining ES6: JavaScript History and What is to Come
Explaining ES6: JavaScript History and What is to ComeExplaining ES6: JavaScript History and What is to Come
Explaining ES6: JavaScript History and What is to Come
 
What can be done with Java, but should better be done with Erlang (@pavlobaron)
What can be done with Java, but should better be done with Erlang (@pavlobaron)What can be done with Java, but should better be done with Erlang (@pavlobaron)
What can be done with Java, but should better be done with Erlang (@pavlobaron)
 
Rust言語紹介
Rust言語紹介Rust言語紹介
Rust言語紹介
 
ES6: Features + Rails
ES6: Features + RailsES6: Features + Rails
ES6: Features + Rails
 
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
 
Rust Mozlando Tutorial
Rust Mozlando TutorialRust Mozlando Tutorial
Rust Mozlando Tutorial
 
Rust concurrency tutorial 2015 12-02
Rust concurrency tutorial 2015 12-02Rust concurrency tutorial 2015 12-02
Rust concurrency tutorial 2015 12-02
 
The mighty js_function
The mighty js_functionThe mighty js_function
The mighty js_function
 
FalsyValues. Dmitry Soshnikov - ECMAScript 6
FalsyValues. Dmitry Soshnikov - ECMAScript 6FalsyValues. Dmitry Soshnikov - ECMAScript 6
FalsyValues. Dmitry Soshnikov - ECMAScript 6
 
ES6 PPT FOR 2016
ES6 PPT FOR 2016ES6 PPT FOR 2016
ES6 PPT FOR 2016
 
Javascript the New Parts v2
Javascript the New Parts v2Javascript the New Parts v2
Javascript the New Parts v2
 
The Ring programming language version 1.7 book - Part 83 of 196
The Ring programming language version 1.7 book - Part 83 of 196The Ring programming language version 1.7 book - Part 83 of 196
The Ring programming language version 1.7 book - Part 83 of 196
 

Similar to JavaScript Survival Guide

AST Transformations at JFokus
AST Transformations at JFokusAST Transformations at JFokus
AST Transformations at JFokus
HamletDRC
 
JavaScript for PHP developers
JavaScript for PHP developersJavaScript for PHP developers
JavaScript for PHP developers
Stoyan Stefanov
 
Jsphp 110312161301-phpapp02
Jsphp 110312161301-phpapp02Jsphp 110312161301-phpapp02
Jsphp 110312161301-phpapp02
Seri Moth
 
AST Transformations
AST TransformationsAST Transformations
AST Transformations
HamletDRC
 

Similar to JavaScript Survival Guide (20)

Ian 20150116 java script oop
Ian 20150116 java script oopIan 20150116 java script oop
Ian 20150116 java script oop
 
Javascript tid-bits
Javascript tid-bitsJavascript tid-bits
Javascript tid-bits
 
JavaScript - Like a Box of Chocolates
JavaScript - Like a Box of ChocolatesJavaScript - Like a Box of Chocolates
JavaScript - Like a Box of Chocolates
 
AST Transformations at JFokus
AST Transformations at JFokusAST Transformations at JFokus
AST Transformations at JFokus
 
JavaScript - Like a Box of Chocolates - jsDay
JavaScript - Like a Box of Chocolates - jsDayJavaScript - Like a Box of Chocolates - jsDay
JavaScript - Like a Box of Chocolates - jsDay
 
JavaScript patterns
JavaScript patternsJavaScript patterns
JavaScript patterns
 
JavaScript - i och utanför webbläsaren (2010-03-03)
JavaScript - i och utanför webbläsaren (2010-03-03)JavaScript - i och utanför webbläsaren (2010-03-03)
JavaScript - i och utanför webbläsaren (2010-03-03)
 
JavaScript for PHP developers
JavaScript for PHP developersJavaScript for PHP developers
JavaScript for PHP developers
 
Jsphp 110312161301-phpapp02
Jsphp 110312161301-phpapp02Jsphp 110312161301-phpapp02
Jsphp 110312161301-phpapp02
 
AST Transformations
AST TransformationsAST Transformations
AST Transformations
 
Groovy Ast Transformations (greach)
Groovy Ast Transformations (greach)Groovy Ast Transformations (greach)
Groovy Ast Transformations (greach)
 
Bologna Developer Zone - About Kotlin
Bologna Developer Zone - About KotlinBologna Developer Zone - About Kotlin
Bologna Developer Zone - About Kotlin
 
Ast transformations
Ast transformationsAst transformations
Ast transformations
 
Introduction kot iin
Introduction kot iinIntroduction kot iin
Introduction kot iin
 
JavaScript Classes and Inheritance
JavaScript Classes and InheritanceJavaScript Classes and Inheritance
JavaScript Classes and Inheritance
 
TypeScript - All you ever wanted to know - Tech Talk by Epic Labs
TypeScript - All you ever wanted to know - Tech Talk by Epic LabsTypeScript - All you ever wanted to know - Tech Talk by Epic Labs
TypeScript - All you ever wanted to know - Tech Talk by Epic Labs
 
Workshop 10: ECMAScript 6
Workshop 10: ECMAScript 6Workshop 10: ECMAScript 6
Workshop 10: ECMAScript 6
 
ES6 generators
ES6 generatorsES6 generators
ES6 generators
 
Say It With Javascript
Say It With JavascriptSay It With Javascript
Say It With Javascript
 
Workshop 1: Good practices in JavaScript
Workshop 1: Good practices in JavaScriptWorkshop 1: Good practices in JavaScript
Workshop 1: Good practices in JavaScript
 

More from Giordano Scalzo

How to Clone Flappy Bird in Swift
How to Clone Flappy Bird in SwiftHow to Clone Flappy Bird in Swift
How to Clone Flappy Bird in Swift
Giordano Scalzo
 
Bdd: Tdd and beyond the infinite
Bdd: Tdd and beyond the infiniteBdd: Tdd and beyond the infinite
Bdd: Tdd and beyond the infinite
Giordano Scalzo
 

More from Giordano Scalzo (12)

The Joy Of Server Side Swift Development
The Joy Of Server Side Swift DevelopmentThe Joy Of Server Side Swift Development
The Joy Of Server Side Swift Development
 
How to Clone Flappy Bird in Swift
How to Clone Flappy Bird in SwiftHow to Clone Flappy Bird in Swift
How to Clone Flappy Bird in Swift
 
A swift introduction to Swift
A swift introduction to SwiftA swift introduction to Swift
A swift introduction to Swift
 
Tame Accidental Complexity with Ruby and MongoMapper
Tame Accidental Complexity with Ruby and MongoMapperTame Accidental Complexity with Ruby and MongoMapper
Tame Accidental Complexity with Ruby and MongoMapper
 
Code kata
Code kataCode kata
Code kata
 
Tdd iPhone For Dummies
Tdd iPhone For DummiesTdd iPhone For Dummies
Tdd iPhone For Dummies
 
Better Software Developers
Better Software DevelopersBetter Software Developers
Better Software Developers
 
Agile Iphone Development
Agile Iphone DevelopmentAgile Iphone Development
Agile Iphone Development
 
XpUg Coding Dojo: KataYahtzee in Ocp way
XpUg Coding Dojo: KataYahtzee in Ocp wayXpUg Coding Dojo: KataYahtzee in Ocp way
XpUg Coding Dojo: KataYahtzee in Ocp way
 
Bdd: Tdd and beyond the infinite
Bdd: Tdd and beyond the infiniteBdd: Tdd and beyond the infinite
Bdd: Tdd and beyond the infinite
 
10 minutes of me: Giordano Scalzo's Visual Resume
10 minutes of me: Giordano Scalzo's Visual Resume10 minutes of me: Giordano Scalzo's Visual Resume
10 minutes of me: Giordano Scalzo's Visual Resume
 
Scrum in an hour
Scrum in an hourScrum in an hour
Scrum in an hour
 

Recently uploaded

Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
vu2urc
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
Joaquim Jorge
 

Recently uploaded (20)

Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 

JavaScript Survival Guide

  • 1. JavaScript Survival Guide Roma, Giordano Scalzo 5 marzo 2011
  • 2. I’m not a guru!
  • 4. Java/C++ guy in the past
  • 6. Why to learn JavaScript?
  • 12. It should be easy...
  • 13. Hacked by Brendan Eich in one week...
  • 19. :-(
  • 21.
  • 24. Essential Scope
  • 25. function sum(x, y){ // implied global result = x + y; return result; } {antipattern}
  • 28. Always declare variables with var function sum(x, y){ var result = x + y; return result; } {pattern}
  • 29. function foo(){ var a = b = 0; //... } {antipattern}
  • 30. b become global function foo(){ var a = (b = 0); //... } {antipattern}
  • 31. don’t use assign chain in definition function foo(){ var a, b; a = b = 0; //... } {pattern}
  • 32. Hoisting myname = "global"; // global variable function func(){ // code... console.log(myname); // "undefined" // code... var myname = "local"; console.log(myname); // "local" } func(); {antipattern}
  • 33. Hoisting myname = "global"; // global variable function func(){ // code... console.log(myname); // "undefined" // code... var myname = "local"; console.log(myname); // "local" } func(); {antipattern}
  • 34. Hoisting myname = "global"; // global variable function func(){ // code... console.log(myname); // "undefined" // code... var myname = "local"; console.log(myname); // "local" } func(); {antipattern}
  • 35. Hoisting myname = "global"; // global variable function func(){ var myname = "declared"; // code... console.log(myname); // "declared" // code... myname = "local"; console.log(myname); // "local" } func(); {pattern}
  • 36. Against minimum vertical distance principle “Variables should be declared as close to their usage as possible” Robert C. Martin - Clean Code
  • 37. Single var pattern function func(){ var a = 1, b = 2, sum = a + b, myobject = {}, i, j; // function body... } {pattern}
  • 38. Don’t forget comma otherwise...
  • 41. In JavaScript almost everything is an object
  • 42. It’s easy... var person = new Object(); person.name = "Scott"; person.say = function(){ return "I am " + this.name; }; console.log(person.say());
  • 43. but wrong! :-( var person = new Object(); person.name = "Scott"; person.say = function(){ return "I am " + this.name; }; console.log(person.say()); {antipattern}
  • 44. var person = {}; person.name = "Scott"; person.say = function(){ return "I am " + this.name; }; console.log(person.say()); {pattern}
  • 45. 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
  • 46. 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
  • 48. 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}
  • 49. Behind the scenes... var Person = function(name){ // var this = {}; // this.prototype = {constructor: this} this.name = name; this.say = function(){ return "I am " + this.name; }; // return this; }; {pattern}
  • 50. 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}
  • 51. What if we forget new?
  • 52. this will point to global object var 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); //object console.log(scott.name); // Scott console.log(typeof adam); //'undefined' console.log(window.name); // Adam
  • 53. this will point to global object var 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); //object console.log(scott.name); // Scott console.log(typeof adam); //'undefined' console.log(window.name); // Adam
  • 54. Enforce new pattern one: naming convention
  • 55. 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}
  • 56. 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}
  • 57. 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
  • 58. 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
  • 60. Define ancestors chain var foo = {one: 1, two: 2}; var bar = {three: 3}; foo.__proto__ = bar; console.log(foo.one); console.log(foo.three);
  • 61. Define ancestors chain var foo = {one: 1, two: 2}; var bar = {three: 3}; foo.__proto__ = bar; console.log(foo.one); console.log(foo.three);
  • 62. console.log(foo.one); bar three: 3 foo one: 1 two: 2 __proto__
  • 63. console.log(foo.one); bar three: 3 foo one: 1 two: 2 __proto__
  • 64. console.log(foo.three); bar three: 3 foo one: 1 two: 2 __proto__
  • 65. console.log(foo.three); bar three: 3 foo one: 1 two: 2 __proto__
  • 66. console.log(foo.three); bar three: 3 foo one: 1 two: 2 __proto__
  • 68. 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; };
  • 69. 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}
  • 70. 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}
  • 71. 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}
  • 72. 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}
  • 73. Essential Functions
  • 74. Functions as first class objects
  • 75. Immediate functions (function(){ alert('watch out!'); })();
  • 76. 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}
  • 78. 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}
  • 79. 1 global! // global object var MYAPP = (function(){ {pattern} var my = {}; // 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
  • 80. 1 global! // global object var MYAPP = (function(){ {pattern} var my = {}; // 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
  • 82. 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}
  • 83. 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}
  • 84. 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}
  • 85. 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}
  • 86. 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}
  • 87. 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}
  • 88. Advanced Test Framework
  • 89. JavaScript is madly in love with Testing.
  • 90. JavaScript is madly in love with Testing. JSUnit
  • 91. JavaScript is madly in love with Testing. JSUnit JSTest
  • 92. JavaScript is madly in love with Testing. QUnit JSUnit JSTest
  • 93. JavaScript is madly in love with Testing. QUnit JSUnit Vows JSTest
  • 94. JavaScript is madly in love with Testing. QUnit JSUnit jsUnitTest Vows JSTest
  • 95. JavaScript is madly in love with Testing. Blue Ridge QUnit JSUnit jsUnitTest Vows JSTest
  • 96. JavaScript is madly in love with Testing. Screw unit Blue Ridge QUnit JSUnit jsUnitTest Vows JSTest
  • 97. JavaScript is madly in love with Testing. Screw unit Blue Ridge QUnit JSUnit YUI Test jsUnitTest Vows JSTest
  • 98. JavaScript is madly in love with Testing. Screw unit Blue Ridge JSpec QUnit JSUnit YUI Test jsUnitTest Vows JSTest
  • 99. JavaScript is madly in love with Testing. Screw unit Blue Ridge JSpec QUnit JSUnit Unitesting YUI Test jsUnitTest Vows JSTest
  • 100. JavaScript is madly in love with Testing. Screw unit Blue Ridge JSpec QUnit JSUnit Unitesting Jasmine YUI Test jsUnitTest Vows JSTest
  • 101. JavaScript is madly in love with Testing. http://pivotal.github.com/jasmine/
  • 102. Jasmine: BDD RSpec-like syntax describe('Array', function() { var array; describe('#unique', function() { beforeEach(function() { array = [3,3,4]; }); it("returns only the unique values in the array", function() { expect(array.unique()).toEqual([3,4]); }); }); });
  • 103. Not mocks and Stubs Spies
  • 104. Jasmine: Spies as Mocks function BetterArray(array){ this.array = array; } BetterArray.prototype = { joinify: function(){ // Does some cool stuff this.array = this.array.join('.'); } }
  • 105. Jasmine: Spies as Mocks describe('BetterArray', function() { var betterArray, anArray = [3,3,4]; beforeEach(function() { betterArray = new BetterArray(anArray); }); describe('#joinify', function() { it("calls the standard join method on Array", function() { var joinSpy = spyOn(betterArray.array, 'join'); betterArray.joinify(); expect(joinSpy).toHaveBeenCalled(); }); }); });
  • 106. Jasmine: Spies as Mocks describe('BetterArray', function() { var betterArray, anArray = [3,3,4]; beforeEach(function() { betterArray = new BetterArray(anArray); }); describe('#joinify', function() { it("calls the standard join method on Array", function() { var joinSpy = spyOn(betterArray.array, 'join'); betterArray.joinify(); expect(joinSpy).toHaveBeenCalled(); }); }); });
  • 107. Jasmine: Spies as Mocks describe('BetterArray', function() { var betterArray, anArray = [3,3,4]; beforeEach(function() { betterArray = new BetterArray(anArray); }); describe('#joinify', function() { it("calls the standard join method on Array", function() { var joinSpy = spyOn(betterArray.array, 'join'); betterArray.joinify(); expect(joinSpy).toHaveBeenCalled(); }); }); });
  • 108. Jasmine: Spies as Mocks describe('BetterArray', function() { var betterArray, anArray = [3,3,4]; beforeEach(function() { betterArray = new BetterArray(anArray); }); describe('#joinify', function() { it("calls the standard join method on Array", function() { var joinSpy = spyOn(betterArray.array, 'join'); betterArray.joinify(); expect(joinSpy).toHaveBeenCalled(); }); }); });
  • 109. Advanced Browser Patterns
  • 110. JavaScript still live into browser...
  • 111. Dom access: write for (var i = 0; i < 100; i += 1) { document.getElementById("result").innerHTML += i + ", "; } {antipattern}
  • 112. Dom access: update local variable var i, content = ""; for (i = 0; i < 100; i += 1) { content += i + ","; } document.getElementById("result").innerHTML += content; {pattern}
  • 113. Dom access: read var padding = document.getElementById("result").style.padding, margin = document.getElementById("result").style.margin; {antipattern}
  • 114. Dom access: read with local variable var style = document.getElementById("result").style, padding = style.padding, margin = style.margin; {pattern}
  • 115. 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}
  • 116. 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}
  • 117. 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}
  • 118. 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}
  • 119. 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}
  • 120. 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}
  • 121. 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}
  • 122. The place of <script> element <!doctype html> <html> <head> <title>My App</title> <script src="all_20110127.js"></script> </head> <body> ... </body> </html> {antipattern}
  • 123. The place of <script> element <!doctype html> <html> <head> <title>My App</title> </head> <body> ... <script src="all_20110127.js"></script> </body> </html> {pattern}
  • 124. It’s just a beginning...
  • 125. Study
  • 126.
  • 127. “Save it for a rainy day!”
  • 128. Check your code with jslint.com
  • 129.
  • 130.
  • 132. http://jashkenas.github.com/coffee-script/ It’s just JavaScript!
  • 133. # 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
  • 134. # 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
  • 135. # 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
  • 136. # 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
  • 137. # 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
  • 138. # 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
  • 139. # 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
  • 140. # 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
  • 141. ...but it’s just another story...
  • 142.
  • 143. giordano.scalzo@cleancode.it @giordanoscalzo www.slideshare.net/giordano github.com/gscalzo Roma,5 marzo 2011 http://creativecommons.org/licenses/by-nc-sa/3.0/