INF397 Full Stack Technologies View Schedule Print

JavaScript Overview

Attention! Code ahead!

Attention! Code ahead!

The bad parts

"Some of the worst ideas in the history of programming languages can be found in JavaScript"
-- Douglas Crockford

"Perhaps my perspective is skewed, because I've seen the real WTFs in JavaScript"
-- Kyle Simpson

The bad parts

  • global scope
  • eval, with, void
  • type coersion
  • arguments meta parameter
  • function statment vs expression
  • incorrect math

  • users run different versions

Bad parts


      //local variable
      var a = 5;
      //implicit global
      b = 10;

      //globals are accessible to any script on the page
      window.a // undefined
      window.b // returns 10

      //Bad math
      0.1 + 0.2 === 0.3 // false
      Number.MIN_VALUE > 0 // true

      //function weirdness
      function () {} // SyntaxError
      var f = function () {} // no problem

      //arguments meta parameter
      (function (a) {
        // a = 1
        arguments[0] = arguments[1];
        // a = 2
      }(1, 2));
    

Bad parts


      //type weirdness
      typeof null // object

      typeof (new String('abc')) // object
      typeof 'abc' //string

      typeof (new Boolean(true)) //object
      typeof true //boolean

      typeof (new Array()) //object
      typeof [] // object

      typeof (new Function()) // function
      typeof function () {} // function

      //Type coersion
      if ([]) { doStuff(); } // gets called
      if ([] == true) { doStuff(); } // DOSN'T get called
      if ([] === false) { doStuff(); } // DOSN'T get called
    

Bad parts


  hello //Error: hello is not defined
  hello! //SyntaxError: Unexpected token !

  //statment position
  function () {} //SyntaxError: Unexpected token (
  (function () {}) //returns the function
  function f() {} //returns undefined, but f is defined

  function f() {}, 'hi' //SyntaxError: Unexpected token ,
  (function f() {}, 'hi') //"hi"

  //Any much more..
    

The hard parts

  • async and event loop
  • prototypal inheritance
  • this, scope and common pitfalls

  • tooling
  • execution context

Prototypical inheritance

The event loop

The good parts

  • Flexible Objects
  • Flexible Functions
  • Lexical Closure

  • OOP & Functional
  • Modern engines

ES2015: The new parts

  • JavaScript language specification, released in June 2015
  • Incrementally implemented in browsers and other environments
  • Introduces a plethora of new features and improvements

Some of the new features in ES2015

  • Arrow functions
  • Classes
  • Object literals syntax
  • Destructuring
  • Default parameters
  • Array spreading
  • Variable declarations
  • Generators
  • Promises
  • Iterators
  • Symbols
  • Number methods
  • Template strings
  • Sets
  • Maps
  • WeakMap

Variable declaration


      //es5
      function incCounter() {
          counter += five;

          if (false) {
              var five = 5;
          }
          //logical error! - the value of five is undefined
      }

      var counter = 0;

      //this code "works" because of var hoisting
  

    //es6
    if (condition) {
        let j = 12; //j exists only inside the if block
    }

    console.log(j); //throws an Error

    const pi = { value: 3.14 }; //pi cannot be reassigned

    pi = 3.14; //throws an Error

    //we can still change properties of the object
    pi.value = 4;

    //the "me" object cannot be changed
    const me = Object.freeze({ name: 'Mihail' });
  

How do const and let help?

  • Clear intent
  • Block scope (const, let)
  • Immutable binding (const)

Arrow functions


      //es5
      [1, 2, 3, 4].map(function square(i) {
          return i*i;
      }); // [1, 4, 9, 16]

      getNumbersAsync(function callback(a, b) {
          return a + b;
      });

      fancyObject.coolMethod = function () {
          var self = this;
          this.elements.forEach(function (el) {
              self.processElement(el); //different "this", use self
          });
      }
  

    //es6
    [1, 2, 3, 4].map(i => i*i); // [1, 4, 9, 16]

    getNumbersAsync((a, b) => a + b);

    fancyObject.coolMethod = () => {
        this.elements.forEach(el => {
            this.processElement(el);
            //error! - "this" doesn't point to fancyObject
        });
    }
  

How do arrow functions help?

  • Concise & Clear intent
  • Uses the outer scope's "this"
  • No arguments meta parameter
  • Not a full substitute of functions

Classes


      //es5
      function Car(model, color) {
          this.model = model;
          this.color = color;
      }

      Car.prototype.startEngine = function () {
          return "Started the engine of the " + this.model;
      };

      var myCar = new Car('Tesla', 'white');
    

      //es6
      class Car {
          constructor(model, color) {
              this.model = model;
              this.color = color;
          }

          startEngine() {
              return "Started the engine of the " + this.model;
          }
      }

      let myCar = new Car('Tesla', 'white');
    

How do classes help?

  • All declarations stay together
  • Methods on the prototype by default

Object literals syntax


      //es5
      var name = 'Mihail',
          myObject = {
              name: name,
              getFriends: function () { ... }
          };

      myObject[getPropertyName()] = 'some value';
    

      //es6
      let name = 'Mihail',
          myObject = {
              name,
              getFriends() { ... },
              [getPropertyName()]: 'some value'
          };
    

How does object literals syntax help?

  • Compact & clear intent
  • All declarations stay together

Destructuring


      //es5
      var coordinates = [23, 14],
          x = coordinates[0],
          y = coordinates[1];

      var personalInfo = getPersonalInfo(),
          name = personalInfo.name,
          age = personalInfo.age,
          petName = personalInfo.pet.name;
    

        //es6
        let [x, y] = [23, 14];

        let { name, age, pet: { name: petName } } = getPersonalInfo();

        //with function parameters
        function sayHi({ name }) {
            console.log('Hi, ' + name);
        }

        sayHi(getPersonalInfo());
    

How does destructuring help?

  • Clear intent
  • Pattern Matching

Array spreading


        //es5
        function variableNumberOfArguments() {
            //hack to get the arguments as an array
            var args = Array.prototype.splice.call(arguments, 0);
        }

        var numbers = [1, 2, 3],
            letters = ['a', 'b', 'c'],
            both = numbers.concat(letters);
    

        //es6
        function variableNumberOfArguments(...args) {
            //args is already an array with all arguments
        }

        let numbers = [1, 2, 3],
            letters = ['a', 'b', 'c'],
            both = [...numbers, ...letters];
    

How does spreading help?

  • Concise and composable
  • No need for the "arguments" parameter

Default parameters


        //es5
        function makeCaption(text, style) {
            text = text || 'default caption';
            style = typeof style === 'object' ? style : { color: 'red' };

            myH1.style.color = style.color;
            myH1.text = text;
        }
    

        //es6
        function h1(text = 'text', { color } = { color: 'red' }) {
            const myH1 = document.createElement('h1');
            myH1.style.color = color;
            myH1.textContent = text;
            return myH1;
        }
    

How do default parameters help?

  • Readability
  • Prevents undefined behaviour

Template strings


        //es5
        "A " + car.color + " " + car.model + " just drove by"
    

        //es6
        `A ${car.color} ${car.model} just drove by`
    

How do template strings help?

  • Built-in template engine
  • Customizable through functions

Sets & Maps


        //es6
        //Sets
        var key = 'any type of value',
            set = new Set();

        set.add(key);
        set.delete(key);
        set.has(key) //returns true or false

        //Maps
        let key = { a: 1 },
            value = { b: 2 },
            map = new Map();

        map.set(key, value);
        map.delete(key);
        map.get(key); //returns value
    

How do sets & maps help?

  • Ability to relate any values types
  • No more abusing objects and arrays
    for sets and maps
  • WeakMap and WeakSet help stop memory leaks
  • Built-in implementations improve performance

Promises


        //es6
        //how to create a promise
        let getData = (url) => new Promise((resolve, reject) => {
            ajax(url, (error, data) => {
                if (error) {
                    reject(error);
                } else {
                    resolve(data);
                }
            });
        });

        //using the promise
        getData('http://somesite.com/data')
            .then(doSomethingClever)
            .catch(logError);
    

Promises


        //es6
        //chaining promises
        getNumbersAsync()
            .then(([a, b]) => a + b)
            .then(checkSumWithServer)
            .then(handleServerResponse)
            .catch(logError);

        //promise helper methods
        Promise.resolve(value) //returns a "thenable" promise
        Promise.reject(error) //returns a "catchable" promise
        Promise.all([array, of, promises]) // waits for all
        Promise.race([array, of, promises]) //the first to resolve wins
    

How do promises help?

  • Clear and natural API
  • Reduce callback hell
  • Future value semantics
  • Invert the flow of control
  • Basis for implementing the async/await pattern

Generators


        //es6
        function* squaresMaker() {
            let i = 1;
            while (true) {
                let step = yield i*i;
                i += step || 1;
            }
        };

        let squares = squaresMaker();
        squares.next();  // { value: 1, done: false }
        squares.next();  // { value: 4, done: false }
        squares.next();  // { value: 9, done: false }
        squares.next(2); // { value: 16, done: false }
        //step = 2
        squares.next();  // { value: 36, done: false }
    

How do generators help?

  • State machine inside a function
  • Two way message passing
  • Co-routines and flow of control
  • Basis for implementing the async/await pattern

Async/Await


        //es7
        async function combinedQuery() {
            let firstAnswer = await firstQuery(),
                secondAnswer = await secondQuery(firstAnswer);

            return secondAnswer;
        }

        //use inside another async function
        async function useQueryAsync() {
            let answer = await combinedQuery();
            doSomethingClever(answer);
        }

        //or use the result as a promise
        function useQuery() {
            combinedQuery().then(doSomethingClever);
        }
    

Annotations


        //es7
        let myObject = {
            //built-in annotation
            @readonly
            myConstant: 42
        };

        myObject.constant = 7; //throws an error

        //annotation definitions are just functions
        function authorized() { ... }

        //using our custom annotation
        @authorized
        function getData() { ... }
    

WebAssembly

  • A byte-code for the web
  • Decouples the language from the runtime
  • Compiled from many languages

Course Schedule:

week 1 03.02.2017 History of the web Fullstack Principles Development Processes Agile Processes DevOps Basics Git
week 2 10.02.2017 Frontend Overview Backend Overview Network Overview Testing JavaScript Overview JavaScript Tooling
week 3 17.02.2017 Web Architectures RESTful principles SOLID principles Web Components Continuous Integration
week 4 24.02.2017 Databases basics Using APIs Deployment Automation Monitoring In-class project consultations
week 5 17.03.2017 Project presentations
Final Test
Course Retrospective and Q&A