Skip to content

Instantly share code, notes, and snippets.

@gpalsingh
Last active March 8, 2018 11:47
Show Gist options
  • Save gpalsingh/feb7c1792ed0ef645ddac8f8cd0406e7 to your computer and use it in GitHub Desktop.
Save gpalsingh/feb7c1792ed0ef645ddac8f8cd0406e7 to your computer and use it in GitHub Desktop.
My notes on course on ES6. Not comprehensive.

Lesson 6: Syntax

  • let: Variables can be reassigned, but can’t be redeclared in the same scope.

  • const: Variables must be assigned an initial value, but can’t be redeclared in the same scope, and can’t be reassigned.

  • Hoisting: Before any JavaScript code is executed, all variables are hoisted, which means they're raised to the top of the function scope.

  • Temporal dead zone: If a variable is declared using let or const inside a block of code, then the variable is stuck in what is known as the temporal dead zone until the variable’s declaration is processed.

  • Suggested to ditch var in place of using let and const.

  • Template literals: Denoted with backticks ( `` ), template literals can contain placeholders which are represented using ${expression}.

  • Examples:

    • Single line:
      let message = `Hi ${student.name} please see ${teacher.name}`
    • Multiline:
      let message = `Hi ${student.name}
                   please see ${teacher.name}`
  • Destructing: Extract data from arrays and objects into distinct variables.

    • Examples:
      • Destructuring values from an array:
        const point = [10, 25, -34];
        const [x, y, z] = point;
        console.log(x, y, z);
      • Destructuring values from an object:
        const gemstone = {
          type: 'quartz',
          color: 'rose',
          karat: 21.29
        };
        
        const {type, color, karat} = gemstone;
        
        console.log(type, color, karat);
  • Object Literal Shorthand:

    • You can remove duplicate variables names from object properties if the properties have the same name as the variables being assigned to them.
    • The function keyword can be dropped.
    • Examples:
      • Original:
        let type = 'quartz';
        let color = 'rose';
        let carat = 21.29;
        
        const gemstone = {
          type: type,
          color: color,
          carat: carat
        };
      • Using Object Literals:
        let gemstone = {
          type,
          color,
          carat,
          calculateWorth() { ... }
        };
  • iterable protocol: Allows javascript objects to define or customize their iteration behaviour.

  • for loop - Example:

    const digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
    
    for (let i = 0; i < digits.length; i++) {
      console.log(digits[i]);
    }
  • For..in loop: Because for...in loops loop over all enumerable properties, this means if you add any additional properties to the array's prototype, then those properties will also appear in the loop.

    • Example:
      const digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
      
      for (const index in digits) {
        console.log(digits[index]);
      }
  • for...of loop:

    • You write a for...of loop almost exactly like you would write a for...in loop, except you swap out in with of and you can drop the index.
    • You can stop or break a for...of loop at anytime.
    • Example:
      const digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
      
      for (const digit of digits) {
        if (digit % 2 === 0) {
          continue;
        }
        console.log(digit);
      }
  • Spread operator: The spread operator, written with three consecutive dots ( ... ), gives you the ability to expand, or spread, iterable objects into multiple elements.

    • Example:
      const fruits = ["apples", "bananas", "pears"];
      const vegetables = ["corn", "potatoes", "carrots"];
      
      const produce = [...fruits, ...vegetables];
  • Rest parameter: The rest parameter, also written with three consecutive dots ( ... ), allows you to represent an indefinite number of elements as an array.

    • Example:
      function sum(...nums) {
        let total = 0;  
        for(const num of nums) {
          total += num;
        }
        return total;
      }
  • Variadic functions: - Functions that take an indefinite number of arguments.

Lesson 7: Functions

  • Arrow function:

    • Regular functions can be either function declarations or function expressions, however arrow functions are always expressions.
    • The parameter list appears before the arrow function's arrow (i.e. =>).
    • If there are two or more items in the parameter list, or if there are zero items in the list, then you need to wrap the list in parentheses.
    • Arrow functions are only expressions.
    • Examples:
      • Concise body syntax:
        1. Has no curly braces surrounding the function body.
        2. Automatically returns the expression.
          const upperizedNames = ['Farrin', 'Kagure', 'Asser'].map(
               name => name.toUpperCase()
          );
      • Block body syntax: If you need more than just a single line of code in your arrow function's body, then you can use the "block body syntax".
        1. It uses curly braces to wrap the function body.
        2. A return statement needs to be used to actually return something from the function.
          const upperizedNames = ['Farrin', 'Kagure', 'Asser'].map( name => {
            name = name.toUpperCase();
            return `${name} has ${name.length} characters in their name`;
          });
  • this keyword:

    • The value of the this keyword is based completely on how its function (or method) is called.
    • Arrow functions inherit their this value from the surrounding context.
  • Default function parameters:

    • To create a default parameter, you add an equal sign ( = ) and then whatever you want the parameter to default to if an argument is not provided.
    • Unless you've got a strong reason to use array defaults with array destructuring, it's recommended to go with object defaults with object destructuring.
    • Example:
      function createSundae({scoops = 1, toppings = ['Hot Fudge']} = {}) {
        const scoopText = scoops === 1 ? 'scoop' : 'scoops';
      return `Your sundae has ${scoops} ${scoopText} with ${toppings.join(' and ')} toppings.`;
      }
  • Classes:

    • ES6 classes are just a mirage and hide the fact that prototypal inheritance is actually going on under the hood.
    • Commas are not used to separate properties or methods in a Class. If you add them, you'll get a SyntaxError of unexpected token ,.
    • When creating a new instance of a JavaScript class, the new keyword must be used.
    • In a subclass constructor function, before this can be used, a call to the super class must be made.
    • Classes use the extends keyword to set itself as a subclass.
    • Example:
      class Tree {
        constructor(size = '10', leaves = {spring: 'green', summer: 'green', fall: 'orange', winter: null}) {
          this.size = size;
          this.leaves = leaves;
          this.leafColor = null;
        }
      
        changeSeason(season) {
          this.leafColor = this.leaves[season];
          if (season === 'spring') {
            this.size += 1;
          }
        }
      }
      
      class Maple extends Tree {
        constructor(syrupQty = 15, size, leaves) {
          super(size, leaves);
          this.syrupQty = syrupQty;
        }
      
        changeSeason(season) {
          super.changeSeason(season);
          if (season === 'spring') {
            this.syrupQty += 1;
          }
        }
      
        gatherSyrup() {
          this.syrupQty -= 3;
        }
      }
      
      const myMaple = new Maple(15, 5);
      myMaple.changeSeason('fall');
      myMaple.gatherSyrup();
      myMaple.changeSeason('spring');
  • Static methods: To add a static method, the keyword static is placed in front of the method name.

Lesson 8 - New Built-ins

  • Symbol: A symbol is a unique and immutable data type that is often used to identify object properties.

    • Example:
    const sym2 = Symbol('banana');
    const sym3 = Symbol('banana');
    console.log(sym2 === sym3);

    false

  • The Iterable Protocol

    • You have the flexibility in ES6 to specify a way for iterating through values in an object.
    • In order for an object to be iterable, it must implement the iterable interface.
    • The iterator method, which is available via the constant [Symbol.iterator], is a zero arguments function that returns an iterator object.
    • An iterator object is an object that conforms to the iterator protocol.
  • The Iterator Protocol

    • The iterator protocol is used to define a standard way that an object produces a sequence of values.
    • An object becomes an iterator when it implements the .next() method.
    • The .next() method is a zero arguments function that returns an object with two properties:
      1. value : the data representing the next value in the sequence of values within the object
      2. done : a boolean representing if the iterator is done going through the sequence of values
        • If done is true, then the iterator has reached the end of its sequence of values.
        • If done is false, then the iterator is able to produce another value in its sequence of values.
  • Sets

    • Sets are not indexed-based - you do not refer to items in a set based on their position in the set.
    • Items in a Set can’t be accessed individually.
    • Use the .size property to return the number of items in a Set.
    • Use the .has() method to check if an item exists in a Set.
    • Use the .values() method to return the values in a Set.
    • Example:
      const games = new Set(['Super Mario Bros.', 'Banjo-Kazooie', 'Mario Kart', 'Super Mario Bros.']);
      
      games.add('Banjo-Tooie');
      games.add('Age of Empires');
      games.delete('Super Mario Bros.');
      console.log(games.size)
  • Using the SetIterator

    • Because the .values() method returns a new iterator object (called SetIterator), you can store that iterator object in a variable and loop through each item in the Set using .next().
    • Example:
      const iterator = months.values();
      iterator.next();
  • WeakSet

    • WeakSet can only contain objects
    • WeakSet is not iterable which means it can’t be looped over
    • WeakSet does not have a .clear() method
    • When an object is deleted, the object will also be deleted from the WeakSet when garbage collection runs.
  • Maps

    • Map is an object that lets you store key-value pairs where both the keys and the values can be objects, primitive values, or a combination of the two.
    • You can’t create Maps from a list of values; instead, you add key-values by using the Map’s .set() method.
    • The .set() method takes two arguments. The first argument is the key, which is used to reference the second argument, the value.
    • To remove key-value pairs, use the .delete() method.
    • You can use the .clear() method to remove all key-value pairs from the Map.
    • The .delete() method returns true if a key-value pair is successfully deleted from the Map object, and false if unsuccessful.
    • The return value of .set() is the Map object itself if successful.
    • You can use the .has() method to check if a key-value pair exists in your Map by passing it a key.
    • You can also retrieve values from a Map, by passing a key to the .get() method.
    • Example:
      const employees = new Map();
      
      employees.set('james.parkes@udacity.com', { 
          firstName: 'James',
          lastName: 'Parkes',
          role: 'Content Developer' 
      });
      employees.delete('julia@udacity.com');
      employees.clear()
      console.log(employees.has('Xavier'));
  • WeakMap

    • WeakMap can only contain objects as keys
    • WeakMap is not iterable which means it can’t be looped
    • WeakMap does not have a .clear() method
    • When an object is deleted, the object key will also be deleted from the WeakMap when garbage collection runs.
    • WeakMaps are useful in situations where you want an efficient, lightweight solution for creating groupings of objects with metadata.
  • Promises

    • A promise will let you start some work that will be done asynchronously.
    • When you create the promise, you give it the code that will be run asynchronously as the argument of the constructor function.
    • Typically the word resolve is used to indicate that this function should be called when the request completes successfully.
    • The resolve method is used to indicate that the request is complete and that it completed successfully.
    • The reject method is used when the request could not be completed.
    • Promises return immediately.
    • Example:
      new Promise(function (resolve, reject) {
        window.setTimeout(function createSundae(flavor = 'chocolate') {
          const sundae = {};
          // request ice cream
          // get cone
          // warm up ice cream scoop
          // scoop generous portion into cone!
          if ( /* iceCreamConeIsEmpty(flavor) */ ) {
              reject(`Sorry, we're out of that flavor :-(`);
          }
          resolve(sundae);
        }, Math.random() * 2000);
      });
  • Proxies

    • The proxy constructor takes two items:
      1. The object that it will be the proxy for
      2. handler: an object containing the list of methods it will handle for the proxied object
    • The get trap is used to intercept calls to properties.
    • If a trap is used, you need to make sure you provide all the functionality for that specific trap.
    • The set trap is used for intercepting code that will change a property.
    • There are actually a total of 13 different traps that can be used in a handler.
    • Example:
      const richard = {status: 'looking for work'};
      const handler = {
          get(target, propName) {
              console.log(target);
              console.log(propName);
              return target[propName];
          }
      
          set(target, propName, value) {
            if (propName === 'payRate') { // if the pay is being set, take 15% as commission
                value = value * 0.85;
            }
            target[propName] = value;
          }
      };
      const agent = new Proxy(richard, handler);
      agent.status; // returns the text `He's following many leads, so you should offer a contract as soon as possible!`
      agent.payRate = 1000; // set the actor's pay to $1,000
      agent.payRate; // $850 the actor's actual pay
  • Generators

    • * is used before function name to mark it as a generator.
    • yield is what causes the generator to pause.
    • With yield name; when the generator is run, it will "yield" the name back out to the function and then pause its execution.
    • .next() will need to be called one more time than there are yield expressions in the generator function.
    • We can also send data back into the generator using the .next() method.
    • You can use generators to handle nested callbacks.
    • Example:
      function* getEmployee() {
          const names = ['Amanda', 'Diego', 'Farrin', 'James', 'Kagure', 'Kavita', 'Orit', 'Richard'];
          const facts = [];
      
          for (const name of names) {
              // yield *out* each name AND store the returned data into the facts array
              facts.push(yield name); 
          }
      
          return facts;
      }
      
      const generatorIterator = getEmployee();
      
      // get the first name out of the generator
      let name = generatorIterator.next().value;
      
      // pass data in *and* get the next name
      name = generatorIterator.next(`${name} is cool!`).value; 
      
      // pass data in *and* get the next name
      name = generatorIterator.next(`${name} is awesome!`).value; 
      
      // pass data in *and* get the next name
      name = generatorIterator.next(`${name} is stupendous!`).value; 
      
      // you get the idea
      name = generatorIterator.next(`${name} is rad!`).value; 
      name = generatorIterator.next(`${name} is impressive!`).value;
      name = generatorIterator.next(`${name} is stunning!`).value;
      name = generatorIterator.next(`${name} is awe-inspiring!`).value;
      
      // pass the last data in, generator ends and returns the array
      const positions = generatorIterator.next(`${name} is magnificent!`).value; 
      
      // displays each name with description on its own line
      positions.join('\n');

Lesson 9 - Professional Developer-fu

  • Ecma International is an industry association that develops and oversees standards like JavaScript and JSON.

  • Polyfill

    • A polyfill, or polyfiller, is a piece of code (or plugin) that provides the technology that you, the developer, expect the browser to provide natively.
    • Avoid overwriting if feature already exists.
    • Polyfills aren't only for patching missing JavaScript features.
  • Transpiling

    • Transpilers are tools that read source code written in one programming language, and produce the equivalent code in another language.
    • The most popular JavaScript transpiler is called Babel.
@aryak007
Copy link

aryak007 commented Mar 8, 2018

Nice work!!.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment