SlideShare una empresa de Scribd logo
1 de 23
Language philosophy, advanced features

ADVANCED JAVASCRIPT

                                         Zsolt Mészárovics <EPAM>
$ whoami
Programming languages:
 Compiled, general purpose: Java; C/C++; Scala
 Scripting: JavaScript; Python; etc…
 Experimental: Go; Dart; CoffeeScript
Recent works (non-project, related to JS):
 NodeJS based stuff involving custom C++ extensions
 Closure Compiler / Closure Templates enhancements
Agenda
 OO Inheritance patterns in JS, which one to use?
 Exploiting functional paradigm support
 Asynchronity in JS
 (still) common pitfalls, how to avoid them?

   Agenda is based on my observations during every day work, working with 3rd party
   sources.
OO & Inheritance Patterns
 Devs tend to trust various frameworks to construct classes with
   inheritance.
Popular types (Crockford’s terms):
 „Pseudoclassical”
 „Power-constructor” or „Parasital”


Trends:
 Avoiding new keyword
 Emulating private members with closures
 Assembling objects from prototypes „by hand”
Pseudo-Classical Pattern
Popular types (Crockfod’s terms):
 „Pseudo-classical”
 „Power-Constructor” or „Parasital”
Concerning trends:
 „Power constructors” – avoiding new keyword
 Emulating private members with closures
 Assembling objects from prototypes „by hand”
Pseudo-Classical Example

    function Shape(x, y) {
         this.x = x;
         this.y = y;
    }

    Shape.prototype.move = function (x, y) {
         this.x += x; this.y += y;
    };

    function Rectangle(x1, y1, x2, y2) {
         Shape.call(this, (x1 + x2) / 2, (y1 + y2) / 2);
         this.x1 = x1; this.x2 = x2; this.y1 = y1; this.y2 = y2;
    }

    Rectangle.prototype = Object.create(Shape.prototype); // may
    poly

    Rectangle.prototype.area = function () {
         return (this.x2 - this.x1) * (this.y2 - this.y1);
    };
Object.create Polyfill



       if (!Object.create) {
           Object.create = function (o) {
               if (arguments.length > 1) {
                   throw new Error('properties not implemented');
               }
               function F() {}
               F.prototype = o;
               return new F();
           };
       }
Power-Constructor Example
     function Shape(x, y) {
          return {
               x: x,
               y: y,
               move: function (x, y) {
                    this.x += x;
                    this.y += y;
               }
          };
     }

     function Rectangle(x1, y1, x2, y2) {
          var self = Shape((x1 + x2) / 2, (y1 + y2) / 2);

         self.x1 = x1; self.x2 = x2;
         self.y1 = y1; self.y2 = y2;

         self.area = function () {
              return (self.x2 - self.x1) * (self.y2 - this.y1);

         };

         return self;
     }
Difference of Resulting Objects
Prototype chain (__proto__):

     „Pseudo-Classical”                 „Power-constructor”

      Rectangle                           Rectangle + Shape

             Shape                             Object

                  Object
                                          Shape

                                               Object

     • layered structure, head object   • flat structure, every head
       has only instance members          object has all members
     • Instantiated with new            • new keyword is optional
       keyword
Which One is Better?
 Power-Constructor pattern is extremely popular. A lot of frameworks
   using it, including jQuery.
 Do we need privates? – not really
 Performance?


Demo time! Let’s evaluate performance with a particle system.
Conclusion
Despite a little bit more verbose, might look not as self-contained than
other variants, Pseudo-Classical inheritance is the way to go.
Advantages:
 Way batter performance, especially at large number of instances
 Better IDE recognition
 Better tooling (Closure-Compiler friendly)
Functional Paradigm: Higher Order Functions
Functions could be passed as arguments, and could be returned by other
functions as return values.


Functions are threated as first-class values.


This provides a flexible way to compose programs.
Example:
Take the sum of the integers between a and b:
    // sum of integers between a and b
    function sumInts(a, b) {
      var sum = 0, i;
      for (i = a; i <= b; i += 1) {
        sum += i;
      }
      return sum;
    }

Take the sum of the cubes of all integers between a and b:
    function cube(n) {
      return Math.pow(n, 3);
    }

    function sumCubes(a, b) {
      var sum = 0, i;
      for (i = a; i <= b; i += 1) {
        sum += cube(i);
      }
      return sum;
    }
Example (continued)


    function   factorial(n) {
      var i,   f = 1;
      for (i   = 2; i <= n; i += 1) {
        f *=   i;
      }
      return   f;
    }

    function sumFactorials(a, b) {
      var sum = 0, i;
      for (i = a; i <= b; i += 1) {
        sum += factorial(i);
      }
      return sum;
    }
Advanced version using higher-order functions
A generic sum:
      function sum(f, a, b) {
        var sum = 0, i;
        for (i = a; i <= b; i += 1) {
          sum += f(i);
        }
        return sum;
      }



Rewritten special cases:
      function identity(n) { return n; }
      sumInts = function (a, b) { return sum(identity, a, b); };
      sumCubes = function (a, b) { return sum(cube, a, b); };
      sumFactorials = function (a, b) { return sum(factorial, a, b); };



Taking functions as parameters, but still a lot of redundancy here…
More advanced version, removed redundancy
Let’s rewrite sum to return a function:
    function sum(fn) {
      return function (a, b) {
         var sum = 0, i;
         for (i = a; i <= b; i += 1) {
           sum += fn(i);
         }
         return sum;
      };
    }


So specific cases could be written as:
    sumInts = sum(identity);
    sumCubes = sum(cube);
    sumFactorials = sum(factorial);

Or could be invoked without the middle-man:
    // equivalent to sumCubes
    sum(cube)(3, 5);
    // sum of the halves of integers between a and b
    sum(function (n) { return Math.round(n / 2); })(3, 5);
Asynchronicity
JS is…
 Event driven
 Single threaded (setTimeout doesn’t do the trick)
      Long running code could block execution, UI responsiveness
 Standard APIs rely on call-backs
    They are often nested multiple levels
    Hard to debug: reading the call-stack is hard; exceptions
     might not get propagated up to the initiator
    „Pyramid of Doom”!
Difficulties with Call-backs
„Pyramid of doom”
When the code marches to the right faster than it marches forward:
  step1(function (value1) {
      step2(value1, function(value2) {
          step3(value2, function(value3) {
              step4(value3, function(value4) {
                  // Do something with value4
              });
          });
      });
  });




This is sequential, what if step3 could be executed when both step1 and
step2 are completed, but those two steps doesn’t depend on each other?
Difficulties with Call-backs (continued)
Synchronizing multiple call-backs
 var callbackACompleted = false;
 var callbackBCompleted = false;

 function callbackA(result) {
        // process result
        callbackACompleted = true;
        if (callbackBCompleted) {
               done();
        }
 }

 function callbackB(result) {
        // process result
        callbackBCompleted = true;
        if (callbackACompleted) {
               done();
        }
 }

 function done() {
        // things to do when boot callbacks completed their jobs
 }

 processA(params, callbackA);
 processB(params, callbackB);
Deferred objects / Promises / Futures
 Designed to solve exactly these problems
 Under used, not widely known


API
 done()
 then()                                      A promise is the stripped down
                           Promise            version of the deferred instance,
 fail()
                        Deferred              doesn’t contain any state mutator
 always()                                    methods.
 resolve()
 reject()


Usage: a task creates a deferred object, and resolves (or fails it) later by
calling .resolve() / .reject(). Clients use promise, which doesn’t provide state
manipulation, just change subscription methods.
Demo
Pitfalls
Array
 Deleting
    delete arr[2]; // [1, 3, undefined × 1, 29, 45, 51]
    arr.splice(2, 1); // ok! [1, 3, 29, 45, 51]
   Never attempt to remove an element from an array with delete, use splice.
 Sorting

        arr = [1, 3, 24, 29, 45, 51];
        arr.sort(); // [1, 24, 29, 3, 45, 51]
        arr.sort(function (x, y) {return x > y;}); // ok

   What happened? Don’t relay on default sort functionality; implement getComparator() ->
   function for objects.
Pitfalls (continued)
Number Conversion
         +"08"; // ok (8)
         +new Date; // .valueOF()
         Number("08"); // same as +
         parseInt("08"); // 0 why?
         parseInt("ff", 16); // 256


  Prefer the + unary operator, you may implement valueOf(), always provide radix for
  parseInt()!


Typeof

         // typeof
         typeof array === "object"; // Array.isArray() (polyfill)
         typeof null === "object"; // spec error :(

  Worst is typeof null, it returns „object” as a result of an early language specification.

Más contenido relacionado

La actualidad más candente

Java 7, 8 & 9 - Moving the language forward
Java 7, 8 & 9 - Moving the language forwardJava 7, 8 & 9 - Moving the language forward
Java 7, 8 & 9 - Moving the language forward
Mario Fusco
 
LinkedIn TBC JavaScript 100: Functions
 LinkedIn TBC JavaScript 100: Functions LinkedIn TBC JavaScript 100: Functions
LinkedIn TBC JavaScript 100: Functions
Adam Crabtree
 
Scala - where objects and functions meet
Scala - where objects and functions meetScala - where objects and functions meet
Scala - where objects and functions meet
Mario Fusco
 
Lec 45.46- virtual.functions
Lec 45.46- virtual.functionsLec 45.46- virtual.functions
Lec 45.46- virtual.functions
Princess Sam
 

La actualidad más candente (20)

Introduction to functional programming using Ocaml
Introduction to functional programming using OcamlIntroduction to functional programming using Ocaml
Introduction to functional programming using Ocaml
 
Memory Management In C++
Memory Management In C++Memory Management In C++
Memory Management In C++
 
Java 7, 8 & 9 - Moving the language forward
Java 7, 8 & 9 - Moving the language forwardJava 7, 8 & 9 - Moving the language forward
Java 7, 8 & 9 - Moving the language forward
 
Memory Management C++ (Peeling operator new() and delete())
Memory Management C++ (Peeling operator new() and delete())Memory Management C++ (Peeling operator new() and delete())
Memory Management C++ (Peeling operator new() and delete())
 
classes & objects in cpp overview
classes & objects in cpp overviewclasses & objects in cpp overview
classes & objects in cpp overview
 
Intro to Functional Programming
Intro to Functional ProgrammingIntro to Functional Programming
Intro to Functional Programming
 
Clojure basics
Clojure basicsClojure basics
Clojure basics
 
Machine-level Composition of Modularized Crosscutting Concerns
Machine-level Composition of Modularized Crosscutting ConcernsMachine-level Composition of Modularized Crosscutting Concerns
Machine-level Composition of Modularized Crosscutting Concerns
 
Functional Programming With Scala
Functional Programming With ScalaFunctional Programming With Scala
Functional Programming With Scala
 
Twins: Object Oriented Programming and Functional Programming
Twins: Object Oriented Programming and Functional ProgrammingTwins: Object Oriented Programming and Functional Programming
Twins: Object Oriented Programming and Functional Programming
 
What's New in C++ 11/14?
What's New in C++ 11/14?What's New in C++ 11/14?
What's New in C++ 11/14?
 
A taste of Functional Programming
A taste of Functional ProgrammingA taste of Functional Programming
A taste of Functional Programming
 
C++ aptitude
C++ aptitudeC++ aptitude
C++ aptitude
 
Map(), flatmap() and reduce() are your new best friends: simpler collections,...
Map(), flatmap() and reduce() are your new best friends: simpler collections,...Map(), flatmap() and reduce() are your new best friends: simpler collections,...
Map(), flatmap() and reduce() are your new best friends: simpler collections,...
 
Category theory, Monads, and Duality in the world of (BIG) Data
Category theory, Monads, and Duality in the world of (BIG) DataCategory theory, Monads, and Duality in the world of (BIG) Data
Category theory, Monads, and Duality in the world of (BIG) Data
 
LinkedIn TBC JavaScript 100: Functions
 LinkedIn TBC JavaScript 100: Functions LinkedIn TBC JavaScript 100: Functions
LinkedIn TBC JavaScript 100: Functions
 
Scala - where objects and functions meet
Scala - where objects and functions meetScala - where objects and functions meet
Scala - where objects and functions meet
 
The STL
The STLThe STL
The STL
 
Lec 45.46- virtual.functions
Lec 45.46- virtual.functionsLec 45.46- virtual.functions
Lec 45.46- virtual.functions
 
Functional programming
Functional programmingFunctional programming
Functional programming
 

Similar a Advanced JavaScript

TI1220 Lecture 6: First-class Functions
TI1220 Lecture 6: First-class FunctionsTI1220 Lecture 6: First-class Functions
TI1220 Lecture 6: First-class Functions
Eelco Visser
 
Bindings: the zen of montage
Bindings: the zen of montageBindings: the zen of montage
Bindings: the zen of montage
Kris Kowal
 
JavaScript (without DOM)
JavaScript (without DOM)JavaScript (without DOM)
JavaScript (without DOM)
Piyush Katariya
 
Столпы функционального программирования для адептов ООП, Николай Мозговой
Столпы функционального программирования для адептов ООП, Николай МозговойСтолпы функционального программирования для адептов ООП, Николай Мозговой
Столпы функционального программирования для адептов ООП, Николай Мозговой
Sigma Software
 

Similar a Advanced JavaScript (20)

TI1220 Lecture 6: First-class Functions
TI1220 Lecture 6: First-class FunctionsTI1220 Lecture 6: First-class Functions
TI1220 Lecture 6: First-class Functions
 
ES6 PPT FOR 2016
ES6 PPT FOR 2016ES6 PPT FOR 2016
ES6 PPT FOR 2016
 
Composition birds-and-recursion
Composition birds-and-recursionComposition birds-and-recursion
Composition birds-and-recursion
 
25-functions.ppt
25-functions.ppt25-functions.ppt
25-functions.ppt
 
TypeScript Introduction
TypeScript IntroductionTypeScript Introduction
TypeScript Introduction
 
EcmaScript 6
EcmaScript 6 EcmaScript 6
EcmaScript 6
 
Intro to Javascript
Intro to JavascriptIntro to Javascript
Intro to Javascript
 
Thinking Functionally with JavaScript
Thinking Functionally with JavaScriptThinking Functionally with JavaScript
Thinking Functionally with JavaScript
 
Object Oriented JavaScript
Object Oriented JavaScriptObject Oriented JavaScript
Object Oriented JavaScript
 
EcmaScript unchained
EcmaScript unchainedEcmaScript unchained
EcmaScript unchained
 
Bindings: the zen of montage
Bindings: the zen of montageBindings: the zen of montage
Bindings: the zen of montage
 
ES6 Overview
ES6 OverviewES6 Overview
ES6 Overview
 
Douglas Crockford: Serversideness
Douglas Crockford: ServersidenessDouglas Crockford: Serversideness
Douglas Crockford: Serversideness
 
Javascript tid-bits
Javascript tid-bitsJavascript tid-bits
Javascript tid-bits
 
Things about Functional JavaScript
Things about Functional JavaScriptThings about Functional JavaScript
Things about Functional JavaScript
 
Is java8a truefunctionallanguage
Is java8a truefunctionallanguageIs java8a truefunctionallanguage
Is java8a truefunctionallanguage
 
Is java8 a true functional programming language
Is java8 a true functional programming languageIs java8 a true functional programming language
Is java8 a true functional programming language
 
JavaScript (without DOM)
JavaScript (without DOM)JavaScript (without DOM)
JavaScript (without DOM)
 
Functional programming
Functional programmingFunctional programming
Functional programming
 
Столпы функционального программирования для адептов ООП, Николай Мозговой
Столпы функционального программирования для адептов ООП, Николай МозговойСтолпы функционального программирования для адептов ООП, Николай Мозговой
Столпы функционального программирования для адептов ООП, Николай Мозговой
 

Advanced JavaScript

  • 1. Language philosophy, advanced features ADVANCED JAVASCRIPT Zsolt Mészárovics <EPAM>
  • 2. $ whoami Programming languages:  Compiled, general purpose: Java; C/C++; Scala  Scripting: JavaScript; Python; etc…  Experimental: Go; Dart; CoffeeScript Recent works (non-project, related to JS):  NodeJS based stuff involving custom C++ extensions  Closure Compiler / Closure Templates enhancements
  • 3. Agenda  OO Inheritance patterns in JS, which one to use?  Exploiting functional paradigm support  Asynchronity in JS  (still) common pitfalls, how to avoid them? Agenda is based on my observations during every day work, working with 3rd party sources.
  • 4. OO & Inheritance Patterns  Devs tend to trust various frameworks to construct classes with inheritance. Popular types (Crockford’s terms):  „Pseudoclassical”  „Power-constructor” or „Parasital” Trends:  Avoiding new keyword  Emulating private members with closures  Assembling objects from prototypes „by hand”
  • 5. Pseudo-Classical Pattern Popular types (Crockfod’s terms):  „Pseudo-classical”  „Power-Constructor” or „Parasital” Concerning trends:  „Power constructors” – avoiding new keyword  Emulating private members with closures  Assembling objects from prototypes „by hand”
  • 6. Pseudo-Classical Example function Shape(x, y) { this.x = x; this.y = y; } Shape.prototype.move = function (x, y) { this.x += x; this.y += y; }; function Rectangle(x1, y1, x2, y2) { Shape.call(this, (x1 + x2) / 2, (y1 + y2) / 2); this.x1 = x1; this.x2 = x2; this.y1 = y1; this.y2 = y2; } Rectangle.prototype = Object.create(Shape.prototype); // may poly Rectangle.prototype.area = function () { return (this.x2 - this.x1) * (this.y2 - this.y1); };
  • 7. Object.create Polyfill if (!Object.create) { Object.create = function (o) { if (arguments.length > 1) { throw new Error('properties not implemented'); } function F() {} F.prototype = o; return new F(); }; }
  • 8. Power-Constructor Example function Shape(x, y) { return { x: x, y: y, move: function (x, y) { this.x += x; this.y += y; } }; } function Rectangle(x1, y1, x2, y2) { var self = Shape((x1 + x2) / 2, (y1 + y2) / 2); self.x1 = x1; self.x2 = x2; self.y1 = y1; self.y2 = y2; self.area = function () { return (self.x2 - self.x1) * (self.y2 - this.y1); }; return self; }
  • 9. Difference of Resulting Objects Prototype chain (__proto__): „Pseudo-Classical” „Power-constructor” Rectangle Rectangle + Shape Shape Object Object Shape Object • layered structure, head object • flat structure, every head has only instance members object has all members • Instantiated with new • new keyword is optional keyword
  • 10. Which One is Better?  Power-Constructor pattern is extremely popular. A lot of frameworks using it, including jQuery.  Do we need privates? – not really  Performance? Demo time! Let’s evaluate performance with a particle system.
  • 11. Conclusion Despite a little bit more verbose, might look not as self-contained than other variants, Pseudo-Classical inheritance is the way to go. Advantages:  Way batter performance, especially at large number of instances  Better IDE recognition  Better tooling (Closure-Compiler friendly)
  • 12. Functional Paradigm: Higher Order Functions Functions could be passed as arguments, and could be returned by other functions as return values. Functions are threated as first-class values. This provides a flexible way to compose programs.
  • 13. Example: Take the sum of the integers between a and b: // sum of integers between a and b function sumInts(a, b) { var sum = 0, i; for (i = a; i <= b; i += 1) { sum += i; } return sum; } Take the sum of the cubes of all integers between a and b: function cube(n) { return Math.pow(n, 3); } function sumCubes(a, b) { var sum = 0, i; for (i = a; i <= b; i += 1) { sum += cube(i); } return sum; }
  • 14. Example (continued)  function factorial(n) { var i, f = 1; for (i = 2; i <= n; i += 1) { f *= i; } return f; } function sumFactorials(a, b) { var sum = 0, i; for (i = a; i <= b; i += 1) { sum += factorial(i); } return sum; }
  • 15. Advanced version using higher-order functions A generic sum: function sum(f, a, b) { var sum = 0, i; for (i = a; i <= b; i += 1) { sum += f(i); } return sum; } Rewritten special cases: function identity(n) { return n; } sumInts = function (a, b) { return sum(identity, a, b); }; sumCubes = function (a, b) { return sum(cube, a, b); }; sumFactorials = function (a, b) { return sum(factorial, a, b); }; Taking functions as parameters, but still a lot of redundancy here…
  • 16. More advanced version, removed redundancy Let’s rewrite sum to return a function: function sum(fn) { return function (a, b) { var sum = 0, i; for (i = a; i <= b; i += 1) { sum += fn(i); } return sum; }; } So specific cases could be written as: sumInts = sum(identity); sumCubes = sum(cube); sumFactorials = sum(factorial); Or could be invoked without the middle-man: // equivalent to sumCubes sum(cube)(3, 5); // sum of the halves of integers between a and b sum(function (n) { return Math.round(n / 2); })(3, 5);
  • 17. Asynchronicity JS is…  Event driven  Single threaded (setTimeout doesn’t do the trick)  Long running code could block execution, UI responsiveness  Standard APIs rely on call-backs  They are often nested multiple levels  Hard to debug: reading the call-stack is hard; exceptions might not get propagated up to the initiator  „Pyramid of Doom”!
  • 18. Difficulties with Call-backs „Pyramid of doom” When the code marches to the right faster than it marches forward: step1(function (value1) { step2(value1, function(value2) { step3(value2, function(value3) { step4(value3, function(value4) { // Do something with value4 }); }); }); }); This is sequential, what if step3 could be executed when both step1 and step2 are completed, but those two steps doesn’t depend on each other?
  • 19. Difficulties with Call-backs (continued) Synchronizing multiple call-backs var callbackACompleted = false; var callbackBCompleted = false; function callbackA(result) { // process result callbackACompleted = true; if (callbackBCompleted) { done(); } } function callbackB(result) { // process result callbackBCompleted = true; if (callbackACompleted) { done(); } } function done() { // things to do when boot callbacks completed their jobs } processA(params, callbackA); processB(params, callbackB);
  • 20. Deferred objects / Promises / Futures  Designed to solve exactly these problems  Under used, not widely known API  done()  then() A promise is the stripped down Promise version of the deferred instance,  fail() Deferred doesn’t contain any state mutator  always() methods.  resolve()  reject() Usage: a task creates a deferred object, and resolves (or fails it) later by calling .resolve() / .reject(). Clients use promise, which doesn’t provide state manipulation, just change subscription methods.
  • 21. Demo
  • 22. Pitfalls Array  Deleting delete arr[2]; // [1, 3, undefined × 1, 29, 45, 51] arr.splice(2, 1); // ok! [1, 3, 29, 45, 51] Never attempt to remove an element from an array with delete, use splice.  Sorting arr = [1, 3, 24, 29, 45, 51]; arr.sort(); // [1, 24, 29, 3, 45, 51] arr.sort(function (x, y) {return x > y;}); // ok What happened? Don’t relay on default sort functionality; implement getComparator() -> function for objects.
  • 23. Pitfalls (continued) Number Conversion +"08"; // ok (8) +new Date; // .valueOF() Number("08"); // same as + parseInt("08"); // 0 why? parseInt("ff", 16); // 256 Prefer the + unary operator, you may implement valueOf(), always provide radix for parseInt()! Typeof // typeof typeof array === "object"; // Array.isArray() (polyfill) typeof null === "object"; // spec error :( Worst is typeof null, it returns „object” as a result of an early language specification.