SlideShare a Scribd company logo
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.

More Related Content

PPTX
Chapter 7 functions (c)
PDF
Functional Programming Patterns for the Pragmatic Programmer
PDF
Functional Programming Patterns (BuildStuff '14)
DOCX
Memory management in c++
PDF
Learning Functional Programming Without Growing a Neckbeard
PDF
Memory Management with Java and C++
PDF
"Немного о функциональном программирование в JavaScript" Алексей Коваленко
PPT
friends functionToshu
Chapter 7 functions (c)
Functional Programming Patterns for the Pragmatic Programmer
Functional Programming Patterns (BuildStuff '14)
Memory management in c++
Learning Functional Programming Without Growing a Neckbeard
Memory Management with Java and C++
"Немного о функциональном программирование в JavaScript" Алексей Коваленко
friends functionToshu

What's hot (20)

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

Similar to Advanced JavaScript (20)

PDF
Whats new in ES2019
PPTX
Academy PRO: ES2015
KEY
Exciting JavaScript - Part I
PDF
ES6, WTF?
PPTX
JavaScript (without DOM)
PDF
JavaScript for PHP developers
PPTX
Awesomeness of JavaScript…almost
KEY
JavaScript Growing Up
PPTX
Typescript barcelona
KEY
Javascript tid-bits
PPTX
Object Oriented JavaScript
PDF
JavaScript 101
PPTX
Functional Programming in Javascript - IL Tech Talks week
PDF
Javascript
PPTX
WEB222-lecture-4.pptx
DOC
Jsphp 110312161301-phpapp02
PDF
ES6 - Next Generation Javascript
PDF
Rediscovering JavaScript: The Language Behind The Libraries
PPT
Douglas Crockford Presentation Goodparts
Whats new in ES2019
Academy PRO: ES2015
Exciting JavaScript - Part I
ES6, WTF?
JavaScript (without DOM)
JavaScript for PHP developers
Awesomeness of JavaScript…almost
JavaScript Growing Up
Typescript barcelona
Javascript tid-bits
Object Oriented JavaScript
JavaScript 101
Functional Programming in Javascript - IL Tech Talks week
Javascript
WEB222-lecture-4.pptx
Jsphp 110312161301-phpapp02
ES6 - Next Generation Javascript
Rediscovering JavaScript: The Language Behind The Libraries
Douglas Crockford Presentation Goodparts
Ad

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.