Skip to content

Instantly share code, notes, and snippets.

@sveggiani
Last active December 10, 2021 15:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sveggiani/e55316d4c5e77500ff147e5888632018 to your computer and use it in GitHub Desktop.
Save sveggiani/e55316d4c5e77500ff147e5888632018 to your computer and use it in GitHub Desktop.
[Javascript - Study notes] #study-notes #javascript

Javascript - Study notes

1. Concepts

1.1. Event Delegation

An event listener is added to a parent element instead of on its descendants. As child events bubbles up DOM the event is triggered. This allows less memory usage and having to handle events after removing or adding descendants.

1.1.1. Event Bubbling

When an event triggers on a DOM element, it will attempt to handle the event if there is a listener attached, then the event is bubbled up to its parent and the same thing happens. This bubbling occurs up the element's ancestors all the way to the document.

Source

1.2. this keyword

  1. When using new to call a function is a new, empty object.
  2. When using apply, call or bind it is the argument passed.
  3. When called as method, it's the object instance that contains the function.
  4. When called as a free function (not the above conditions), it's the global object. (window in browsers)
  5. If multiple rules apply, the rule higher rule wins.
  6. In ES6 arrow functions, it's the surrounding scope at the moment of its creation.

Source / Source 2

1.3. Prototypal Inheritance

Javascript objects have a prototype property with a reference to a base or creator object. When a property of the object is requested, if not found in the object, it will look on it's prototype, in its protype's prototype and so on. This works more delegating than copying or classical inheritance.

1.4. Differences between apply, call and bind methods

  • apply: executes a function passing a single array containing the arguments.
  • call: executes a function passing multiple arguments.
  • bind: creates a new function passing the first parameter as this and the next parameters as arguments.

1.5. Modules

Intended to deal with encapsulation and dependencies.

Source

1.5.1. Module Pattern

  • Cannot import other modules
  • no async loading
function EmployeeDetails() {
  var name: "Mayank";
  var age = 30;
  var designation = "Developer",
  var salary = 10000;


  
  return {
    name: name,
    age: age,
    designation: designation
  }
}

var newEmployee = EmployeeDetails()

// This will result in "undefined" value
var userName = newEmployee.salary;

1.5.2. AMD

  • Asynchronous (better startup times)
  • Browser oriented
  • Dependency management fully integrated.
  • Verbose
// define(id?, dependencies?, factory);

define("alpha", ["require", "exports", "beta"], function (require, exports, beta) {
  exports.verb = function() {
    return beta.verb();
    //Or:
    return require("beta").verb();
  }
});

1.5.3. CommonJS

  • Synchronous.
  • Server oriented.
  • Almost the same than Node Modules.
  • exports object which contains what will be outputed. Bound to module.exports.
  • module.exports is an special object that takes exports and actually is exported.
function myModule() {
  this.hello = function() {
    return 'hello!';
  }

  this.goodbye = function() {
    return 'goodbye!';
  }
}

module.exports = myModule;

// USAGE
var myModule = require('myModule');
var myModuleInstance = new myModule();
myModuleInstance.hello(); // 'hello!'
myModuleInstance.goodbye(); // 'goodbye

1.5.4. ES2015 Modules

  • Synchronous and Asynchronous compatibility.
  • import directive is not dynamic. Cannot be called in any place.

1.6. IIFE (Immediately Invoked Function Expressions)

  • for data privacy
  • avoid collitions by not polluting the global namespace or scope.
  • helps with code minification.
  • reduce scope lookups (references are resolved faster).
  • ES5 let comes to solve the scope encapsulation problem too.
(function () {
    var aName = "Barry";
})();

Source

1.7. Differences between null, undefined and undeclared

  • undeclared: not declared with var, let or const. Throws an error in strict mode. Checked with try/catch. BAD!
  • undefined: declared but not assigned. Check with ===, typeof x === 'undefined' or x === undefined.
  • null: explicitely assigned. Represents no value. Check with === operator.

Source

1.8. Closures

  • A closure is the combination of a function and the lexical environment within which that function was declared.

  • Functions that have access to the outer (enclosing) function's variables—scope chain even after the outer function has returned.

  • Used in the Module Pattern, emulating private methods.

  • Source #1

  • Source #2

1.8.1. Lexical Scoping

Describes how a parser resolves variable names when functions are nested. The word "lexical" refers to the fact that lexical scoping uses the location where a variable is declared within the source code to determine where that variable is available. Nested functions have access to variables declared in their outer scope.

1.8.2. Environment

This environment consists of any local variables that were in-scope at the time the closure was created.

1.9. Differences between forEach and map methods

The main difference between .forEach() and .map() is that .map returns a new array. If you need the result, but do not wish to mutate the original array, .map is the clear choice. If you simply need to iterate over an array, forEach is a fine choice.

Source

1.10. Anonymous Functions

Functions dynamically declared at runtime. They aren’t given a name in the same way as normal functions.

  • Used in IIFE's
  • Function callbacks (e.g. setTimeout())
  • Arguments for functions / functional programming

1.11. Objects

1.11.1. Native Objects

Native objects are objects that are part of the JavaScript language defined by the ECMAScript specification, such as String, Math, RegExp, Object, Function.

1.11.2. Host Objects

Host objects are provided by the runtime environment (browser or Node), such as window, XMLHTTPRequest, etc.

1.12. High-order Functions

Is a function that: takes one or more functions as arguments (i.e. procedural parameters), returns a function as its result.

1.13. AJAX

Ajax (asynchronous JavaScript and XML) is a set of web development techniques using many web technologies on the client side to create asynchronous web applications.

1.14. JSONP

Is a method commonly used to bypass the cross-domain policies in web browsers because Ajax requests from the current page to a cross-origin domain is not allowed. Works by making a request to a cross-origin domain via a <script> tag and usually with a callback query parameter, for example: https://example.com?callback=printData. The server will then wrap the data within a function called printData and return it to the client.

1.15. CORS (Cross-origin resource sharing)

Cross-Origin Resource Sharing (CORS) is a mechanism that uses additional HTTP headers to tell a browser to let a web application running at one origin (domain) have permission to access selected resources from a server at a different origin.Cross-Origin Resource Sharing (CORS) is a mechanism that uses additional HTTP headers to tell a browser to let a web application running at one origin (domain) have permission to access selected resources from a server at a different origin.

Source

1.16. Hoisting

Hoisting is a term used to explain the behavior of variable declarations in your code. Variables declared or initialized with the var keyword will have their declaration "moved" up to the top of the current scope, which we refer to as hoisting. However, only the declaration is hoisted, the assignment (if there is one), will stay where it is. Declarations with let and const are not hoisted.

Function declarations have the body hoisted while the function expressions (written in the form of variable declarations) only has the variable declaration hoisted.

1.17. Event Loop

Phillip Roberts talk explaining What the heck is the Event Loop.

1.17.1. EL Concepts

TBD

2. Language Features

2.1 ES6

2.1.1. var / let / const to declare variables

  • var: allows the variable to be reasigned and re-declared. Declaration is made at function scope and could cause unintentional modifications.
  • let: doesn't allow to be reasigned (you cannot do let more than once). Declaration is made at block scope. Allows reasignment.
  • const: variables declared with const cannot be redeclared nor re-declared. Although, in objects, properties can be changed. Declaration is made at block scope.

2.1.2. Arrow functions

  • Implicit return: you need to wrap the returned object in parenthesis:
    const myObject = otherObject.map(item, i) => ({ name: item, username: item + 'username', index: i }))
    you cannot just do:
    const myObject = otherObject.map(item, i) => { name: item, username: item + 'username', index: i })
  • Convenient return (a boolean) evaluating a condition:
    const older = ages.filter(age => age >= 60)
  • value of this is not automatically bouded to function
    const box = document.querySelector('.box')
    box.addEventListener('click', () => { console.log(this) })
    // will output "window" instead of box

2.1.3. Template strings

  • Template strings (TS) are declared using backsticks:
    const name = 'Template string'
    const template = `This is a ${name} and it's awesome! No more contatenation :)`
  • Expressions can be used inside a TS:
    const dogAge = 7
    const template = `the dog age is ${dogAge * 7}`
  • TS supports multiline content:
    const template = `
      <div>
        <h1>My headline</h1>
      </div>
    `
  • Looping inside a TS is possible:
    const dogs = [
      { name: 'Snickers', age: 2 },
      { name: 'Hugo', age: 8 },
      { name: 'Sunny', age: 1 }
    ]
    
    const markup = `
      <ul class="dogs">
        ${dogs.map(dog => `
          <li>${dog.name} is ${dog.age * 7}</li>
        `).join('')}
      </ul>
    `
  • Tagged template literals:
    function highlight(strings, ...values) {
      let str = '';
      strings.forEach((string, i) => {
        str += `${string} <span contenteditable class="hl">${values[i] || ''}</span>`;
      });
      return str;
    }
    
    const name = 'Snickers';
    const age = 100;
    
    const sentence = highlight`My dog's name is ${name} and he is ${age} years old`;

2.1.4. New string methods

All these expressions returns true:

  • 'Contact, 1997'.startsWith('Con')
  • 'Contact, 1997'.startsWith('19', 8)
  • 'Contact, 1997'.endsWith('97')
  • 'Contact, 1997'.endsWith('act', 7)
  • 'This is a sentence.'.includes('is')
  • '🚀'.repeat(3) === '🚀🚀🚀'

2.2. Promises + async/await

The Promise object represents the eventual completion (or failure) of an asynchronous operation and its resulting value.

  • Callbacks added with then() will never be invoked before the completion of the current run of the JavaScript event loop.
  • These callbacks will be invoked even if they were added after the success or failure of the asynchronous operation that the promise represents.
  • Multiple callbacks may be added by calling then() several times. They will be invoked one after another, in the order in which they were inserted.
function getImage(file) {
  return new Promise((resolve, reject) => {
    try {
      const data = readFile(file)
      resolve(data)
    } catch (err) {
      reject(new Error(err))
    }
  })
}

getImage(file)
  .then(image => console.log(image))
  .catch(err => console.log(err))
  .finally(() => console.log("All done!"))
// Promise chain example
doSomething()
.then(function(result) {
  return doSomethingElse(result);
})
.then(newResult => doThirdThing(newResult))
.then(() => doFourthThing())
.catch(error => console.error(error));

The async and await keywords enable asynchronous, promise-based behavior to be written in a cleaner style, avoiding the need to explicitly configure promise chains.

// Rewriting a Promise chain with an async function (not the previous example)
async function getProcessedData(url) {
  let v
  try {
    v = await downloadData(url)
  } catch(e) {
    v = await downloadFallbackData(url)
  }
  return processDataInWorker(v)
}

The Promise.all() method takes an iterable of promises as an input, and returns a single Promise that resolves to an array of the results of the input promises.

const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, 'foo');
});

Promise.all([promise1, promise2, promise3]).then((values) => {
  console.log(values);
});
// expected output: Array [3, 42, "foo"]

The Promise.race() method returns a promise that fulfills or rejects as soon as one of the promises in an iterable fulfills or rejects, with the value or reason from that promise.

const promise1 = new Promise((resolve, reject) => {
  setTimeout(resolve, 500, 'one');
});

const promise2 = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, 'two');
});

Promise.race([promise1, promise2]).then((value) => {
  console.log(value);
  // Both resolve, but promise2 is faster
});
// expected output: "two"

3. Objects

3.1. Inmutability

  • An object can be made "somehow" inmutable by using Object.freeze(). However it is not necesarilly a constant.

4. Types

4.1. Objects

Objects are simple name / value collections. They are similar to hash tables (C, C++), hash maps (Java) or associative arrays (PHP). name is a string and its value any other type (including objects).

  • Literal object declaration (var obj = {}) is preferred.

4.2. Values and object evaluations

The following items evaluates as false: false, 0, "", NaN, null and undefined. Any other value evaluates as true.

5. Tools

6. Resources

7. To-DO

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