LAMP-1-600x338

 

http://singlepageappbook.com/goal.html

 

 


 


 

 

;(function() {

    // Bad: global names = global state

    window.FooMachine = {};

    // Bad: implementation detail is made publicly accessible

    FooMachine.processBar = function () { ... };

    FooMachine.doFoo = function(bar) {

      FooMachine.processBar(bar);

      // ...

    };

 

    // Bad: exporting another object from the same file!

    // No logical mapping from modules to files.

    window.BarMachine = { ... };

  })();

 

  ;(function() {

    // Good: the name is local to this module

    var FooMachine = {};

 

    // Good: implementation detail is clearly local to the closure

    function processBar() { ... }

 

    FooMachine.doFoo = function(bar) {

      processBar(bar);

      // ...

    };

 

    // Good: only exporting the public interface,

    // internals can be refactored without worrying

    return FooMachine;

  })();

 

 

Do not leak global variables

Do not expose implementation details

Do not mix definition and instantiation/initialization

Do not modify objects you don't own

 

 

 

Lexical Scope

 

Another point to mention is the lexical scope. Lexical scope means the children scope

have the access to the variables defined in the parent scope.

 

 

 

 

 

function checkScope()   {

    var or let or none i = "func ";

    {

      let i = "block";

      console.log(i);

    }

    console.log(i);

 

  }

  checkScope();

 

block

func

 

  function checkScope()   {

    var i = "func ";

    {

      var i = "block";

      console.log(i);

    }

    console.log(i);

 

  }

  checkScope();

 

block

block

 

  function checkScope()   {

    let i = "func ";

    {

      var i = "block";

      console.log(i);

    }

    console.log(i);

 

  }

  checkScope();

 

Uncaught SyntaxError: Identifier 'i' has already been declared

 

  function checkScope()   {

     let or none i = "func ";

    {

      console.log(i);

      let i = "block";

      console.log(i);

    }

    console.log(i);

 

  }

  checkScope();

 

blockscope.htm:11 Uncaught ReferenceError: Cannot access 'i' before initialization

 

  function checkScope()   {

 

    {

 

      let i = "block";

      console.log(i);

    }

    console.log(i);

 

  }

 

blockscope.htm:15 Uncaught ReferenceError: i is not defined

 

  function checkScope()   {

 

    {

 

      Var or none i = "block";

      console.log(i);

    }

    console.log(i);

 

  }

  checkScope();

 

block

block

 

  function checkScope()   {

    var or let or none i = "block";

    {

      console.log(i);

    }

    console.log(i);

  }

  checkScope();

 

block

block

 

 

 

 

Create Strings using Template literals

 

 

const person = {

  name: 'saravan',

}

const greeting = `Hello ${person.name}

  what is your age?`

 

console.log(greeting)

 

Hello saravan

      what is your age?

 

Object literals

 

const createPerson = (name) => { return {name: name} }

console.log(createPerson("santhosh"));

 

or simply

 

const createPerson = (name) => { return {name} }

console.log(createPerson("santhosh"));



const bicycle = {

  gear: 2,

  setGear : function (newGear) {

    this.gear = newGear;

  }

}

 

bicycle.setGear(3)

console.log(bicycle.gear)

 

or simply

 

const bicycle = {

  gear: 2,

  setGear (newGear) {

    this.gear = newGear;

  }

}

 

bicycle.setGear(3)

console.log(bicycle.gear)

 

var oldClass = function(myvar) {

  this.something = myvar

}

 

var myobj = new oldClass('saravan')

 

console.log(myobj.something)

 

class newClass {

  constructor(myvar) {

    this.something = myvar

  }

}

 

var myobj = new newClass('saravan')

console.log(myobj.something)

 

function makeClass() {

  class newClass {

    constructor(myvar) {

      this.something = myvar

    }

  }

  return newClass

}

 

const returnedClass = makeClass()

 

var myobj = new returnedClass('saravan')

console.log(myobj.something)

 

 

ConstructorPattern:

 

var peopleConstructor = function (name, age, state) {

  this.age = age

  this.name = name

  this.state = state

 

  this.printPerson = function () {

    print(this.name + ', ' + this.age + ', ' + this.state)

  }

}

 

// new is required

var person1 = new peopleConstructor('john', 23, 'CA')

var person2 = new peopleConstructor('kim', 27, 'SC')

 

person1.printPerson()

person2.printPerson()

 

FactoryPattern:

 

var peopleFactory = function (name, age, state) {

  var temp = {}

  temp.age = age

  temp.name = name

  temp.state = state

 

  temp.printPerson = function () {

    print(this.name + ', ' + this.age + ', ' + this.state)

  }

 

  // new object will be created everytime. return that object

  return temp

}

 

var person1 = peopleFactory('john', 23, 'CA')

var person2 = peopleFactory('kim', 27, 'SC')

 

person1.printPerson()

person2.printPerson()

 

PrototypePattern:

 

var peopleProto = function () {}

 

peopleProto.prototype.age = 0

peopleProto.prototype.name = 'no name'

peopleProto.prototype.city = 'no city'

peopleProto.prototype.printPerson = function () {

  print(this.name + ', ' + this.age + ', ' + this.state)

}

 

var person1 = new peopleProto()

//person1.name = 'john';

person1.age = 23

person1.city = 'CA'

person1.printPerson()

print('name' in person1)

print(person1.hasOwnProperty('name'))

 

CreateFromObject:

 

 

var Pizza = {

  crust: 'then',

  toppings: 3,

  hasBacon: true,

  howmanyToppings: function () {

    return this.toppings

  },

}

 

var Pizza = function () {

  var crust = 'thin'

  var toppings = 3

  this.hasBacon = true

 

  this.getHasBacon = function () {

    return this.hasBacon

  }

 

  this.getCrust = function () {

    return crust

  }

 

  var getToppings = function () {

    return toppings

  }

 

  var tmp = {}

  tmp.getToppings = getToppings

  return tmp

}

 

var PizzaA = new Pizza()

print(PizzaA.getToppings())

 

DynamicPrototypePattern:

 

 

var peopleDynamicProto = function (name, age, state) {

  this.age = age

  this.name = name

  this.state = state

 

  this.printPerson = function () {

    print(this.name + ', ' + this.age + ', ' + this.state)

  }

 

  if (typeof this.printPerson !== 'function') {

    peopleDynamicProto.prototype.printPerson = function () {

      print(this.name + ', ' + this.age + ', ' + this.state)

    }

  }

}

 

var person1 = new peopleDynamicProto('john', 23, 'CA')

person1.printPerson()

 

 

 


 


 

 

    var obj = { num: 2 };

 

    var addToThis = function (a) {

        return this.num + a;

    };

 

    print(addToThis.call(obj, 3));

   

    var addToThis = function (a, b, c) {

        return this.num + a + b + c;

    };

 

    print(addToThis.call(obj, 1, 2, 3));

 

    var obj2 = { num: 5 };

 

    var arr = [1, 2, 3];

 

    print(addToThis.apply(obj, arr));

    print(addToThis.apply(obj2, arr));

 

    var bound = addToThis.bind(obj);

 

    console.dir(bound);

 

    print(bound(1, 2, 3));

 

 

Object properties can be accessed by using the dot notation or the bracket notation:

 

const myObj = {

    foo: 'bar',

    age: 42

  }myObj.foo // 'bar' accessed through dot notation

  myObj['age'] // 42 accessed through bracket notation

 

  The object destructuring assignment syntax gives us a third way to access object properties:

 

  const { foo } = myObj // 'bar'

  const { age } = myObj // 42// or all in one line:const { foo, age } = myObj // foo === 'bar', age === 42

 

 

 

  getPropValue

 

  export const getPropValue = (obj, key) =>

    key.split('.').reduce((o, x) =>

      o == undefined ? o : o[x]

    , obj)

 

   (Note that the double equals ==checks for both undefined and null )

  We could pass in a key of the form prop.nestedprop.nestedprop and it would happily return the value for that nested property.

  For example, if the object were:

  const obj = {

      main: {

        content: {

          title: 'old pier',

          description: 'seagulls paradise'

        }

      }

    }

   

  we could retrieve the title as:

 

  const title = getPropValue(obj, 'main.content.title')

  // 'old pier'

 

 

 

  obj || {}

 

 

  const obj = {

      main: 'Brighton seagull'

    }

    const { main } = obj || {}

    // 'Brighton seagull'

 

  https://devhints.io/flow

 

 

 

 

 

 

 

https://www.sitepoint.com/use-jquerys-ajax-function/

 

jQuery’s most-used Ajax shorthand methods: $.get(), $.post(), and $.load()

 

$('#main-menu a').on('click', function(event) {

  event.preventDefault();

 

  $('#main').load(this.href + ' #main *', function(responseText, status) {

  if (status === 'success') {

    $('#notification-bar').text('The page has been successfully loaded');

  } else {

      $('#notification-bar').text('An error occurred');

    }

  });

});

 

Updating this snippet to employ the $.ajax() function, we obtain the code shown below:

 

$('#main-menu a').on('click', function(event) {

  event.preventDefault();

 

  $.ajax(this.href, {

    success: function(data) {

      $('#main').html($(data).find('#main *'));

      $('#notification-bar').text('The page has been successfully loaded');

},

    error: function() {

      $('#notification-bar').text('An error occurred');

    }

  });

});

 

The code to achieve this goal is as follows:

 

$.ajax({

  url: 'http://api.joind.in/v2.1/talks/10889',

  data: {

    format: 'json'

  },

  error: function() {

    $('#info').html('<p>An error has occurred</p>');

  },

  dataType: 'jsonp',

  success: function(data) {

    var $title = $('<h1>').text(data.talks[0].talk_title);

    var $description =  $('<p>').text(data.talks[0].talk_description);

    $('#info')

    .append($title)

    .append($description);

  },

  type: 'GET'

});

 

 

 

 

 

 

https://www.toptal.com/javascript/functional-programming-javascript

 

Pure vs. Impure Functions

Pure functions take some input and give a fixed output. Also, they cause no side effects in the outside world.

 

const add = (a, b) => a + b;

 

Here, add is a pure function. This is because, for a fixed value of a and b, the output will always be the same.

 

const SECRET = 42;  

const getId = (a) => SECRET * a;

 

getId is not a pure function. The reason being that it uses the global variable SECRET for computing the output. If SECRET were to change, the getId function will return a different value for the same input. Thus, it is not a pure function.

 

 

Creating Your Own Pure Function

We can create our pure function as well. Let’s do one for duplicating a string n number of times.

 

const duplicate = (str, n) =>  

    n < 1 ? '' : str + duplicate(str, n-1);

This function duplicates a string n times and returns a new string.

duplicate('hooray!', 3)  

// hooray!hooray!hooray!

 

 

Higher-order Functions

Higher-order functions are functions that accept a function as an argument and return a function. Often, they are used to add to the functionality of a function.

 

const withLog = (fn) => {  

    return (...args) => {  

        console.log(`calling ${fn.name}`);  

        return fn(...args);  

    };  

};

 

In the above example, we create a withLog higher-order function that takes a function and returns a function that logs a message before the wrapped function runs.

 

const add = (a, b) => a + b;  

const addWithLogging = withLog(add);  

addWithLogging(3, 4);  

// calling add  

// 7

 

withLog HOF can be used with other functions as well and it works without any conflicts or writing extra code. This is the beauty of a HOF.

 

const addWithLogging = withLog(add);  

const hype = s => s + '!!!';  

const hypeWithLogging = withLog(hype);  

hypeWithLogging('Sale');  

// calling hype  

// Sale!!!

One can also call it without defining a combining function.

withLog(hype)('Sale');

// calling hype  

// Sale!!!

 

 

Currying

Currying means breaking down a function that takes multiple arguments into one or multiple levels of higher-order functions.

 

Let’s take the add function.

 

const add = (a, b) => a + b;

 

When we are to curry it, we rewrite it distributing arguments into multiple levels as follows.

 

const add = a => {

    return b => {

        return a + b;

    };

};

add(3)(4);  

// 7

 

 

The benefit of currying is memoization. We can now memoize certain arguments in a function call so that they can be reused later without duplication and re-computation.

 

 

// assume getOffsetNumer() call is expensive

const addOffset = add(getOffsetNumber());

addOffset(4);

// 4 + getOffsetNumber()

addOffset(6);

 

This is certainly better than using both arguments everywhere.

 

// (X) DON"T DO THIS  

add(4, getOffsetNumber());  

add(6, getOffsetNumber());  

add(10, getOffsetNumber());

 

 

We can also reformat our curried function to look succinct. This is because each level of the currying function call is a single line return statement. Therefore, we can use arrow functions in ES6 to refactor it as follows.

 

const add = a => b => a + b;

 

Composition

 

In mathematics, composition is defined as passing the output of one function into input of another so as to create a combined output. The same is possible in functional programming since we are using pure functions.

 

To show an example, let’s create some functions.

The first function is range, which takes a starting number a and an ending number b and creates an array consisting of numbers from a to b.

 

const range = (a, b) => a > b ? [] : [a, ...range(a+1, b)];

 

Then we have a function multiply that takes an array and multiplies all the numbers in it.

 

const multiply = arr => arr.reduce((p, a) => p * a);

 

We will use these functions together to calculate factorial.

 

const factorial = n => multiply(range(1, n));  

factorial(5);  

// 120  

factorial(6);  

// 720

 

The above function for calculating factorial is similar to f(x) = g(h(x)), thus demonstrating the composition property.

 

Higher-Order Functions

A higher-order function is a function that gets a function as an argument. It may or may not return a function as its resulting output.

Here’s an example of Higher-Order Function:

 

 

 

Function Composition

 

Functional Programming won’t be completely functional without this feature. Function Composition is an act of composing/creating functions that allow you to further simplify and compress your functions by taking functions as an argument and return an output. It may also return another function as its output other than numerical/string values.

Here is an example of Function Composition:

 

var compose = (f, g) => (x) => f(g(x));

 

    let list = [1, 2, 3, 4, 5];

    let accumulator = 0;

   

 

    function sum(list, accumulator) {

      if (list.length == 0) {

        return accumulator;

      }

   

 

      return sum(list.slice(1), accumulator + list[0]);

    }

   

 

    sum(list, accumulator); // 15

    list; // [1, 2, 3, 4, 5]

    accumulator; // 0

 

 

 

 

 

 

 

A Principle Of Object Oriented Design (Composition Over Class ...

 

SPLICE

 

let arr = ["I", "study", "JavaScript"];

 

arr.splice(1, 1); // from index 1 remove 1 element

 

alert( arr ); // ["I", "JavaScript"]

 

let arr = ["I", "study", "JavaScript", "right", "now"];

 

// remove 3 first elements and replace them with another

arr.splice(0, 3, "Let's", "dance");

 

alert( arr ) // now ["Let's", "dance", "right", "now"]

 

let arr = ["I", "study", "JavaScript", "right", "now"];

 

// remove 2 first elements

let removed = arr.splice(0, 2);

 

alert( removed ); // "I", "study" <-- array of removed elements

 

let arr = ["I", "study", "JavaScript"];

 

// from index 2

// delete 0

// then insert "complex" and "language"

arr.splice(2, 0, "complex", "language");

 

alert( arr ); // "I", "study", "complex", "language", "JavaScript"

 

let arr = [1, 2, 5];

 

// from index -1 (one step from the end)

// delete 0 elements,

// then insert 3 and 4

arr.splice(-1, 0, 3, 4);

 

alert( arr ); // 1,2,3,4,5

 

SLICE

 

let arr = ["t", "e", "s", "t"];

 

alert( arr.slice(1, 3) ); // e,s (copy from 1 to 3)

 

alert( arr.slice(-2) ); // s,t (copy from -2 till the end)

 

let arr = [1, 2];

 

// create an array from: arr and [3,4]

alert( arr.concat([3, 4]) ); // 1,2,3,4

 

// create an array from: arr and [3,4] and [5,6]

alert( arr.concat([3, 4], [5, 6]) ); // 1,2,3,4,5,6

 

// create an array from: arr and [3,4], then add values 5 and 6

alert( arr.concat([3, 4], 5, 6) ); // 1,2,3,4,5,6

 

let arr = [1, 2];

 

let arrayLike = {

  0: "something",

  1: "else",

  [Symbol.isConcatSpreadable]: true,

  length: 2

};

 

alert( arr.concat(arrayLike) ); // 1,2,something,else

 

let countries = ['Österreich', 'Andorra', 'Vietnam'];

 

alert( countries.sort( (a, b) => a > b ? 1 : -1) ); // Andorra, Vietnam, Österreich (wrong)

["Bilbo", "Gandalf", "Nazgul"].forEach(alert);

 

["Bilbo", "Gandalf", "Nazgul"].forEach((item, index, array) => {

  alert(`${item} is at index ${index} in ${array}`);

});

 

let result = arr.find(function(item, index, array) {

  // if true is returned, item is returned and iteration is stopped

  // for falsy scenario returns undefined

});

 

let users = [

  {id: 1, name: "John"},

  {id: 2, name: "Pete"},

  {id: 3, name: "Mary"}

];

 

let user = users.find(item => item.id == 1);

 

alert(user.name); // John

 

let users = [

  {id: 1, name: "John"},

  {id: 2, name: "Pete"},

  {id: 3, name: "Mary"}

];

 

// returns array of the first two users

let someUsers = users.filter(item => item.id < 3);

 

alert(someUsers.length); // 2

 

let lengths = ["Bilbo", "Gandalf", "Nazgul"].map(item => item.length);

alert(lengths); // 5,7,6

 

let arr = [ 1, 2, 15 ];

 

// the method reorders the content of arr

arr.sort();

 

alert( arr );  // 1, 15, 2

 

function compareNumeric(a, b) {

  if (a > b) return 1;

  if (a == b) return 0;

  if (a < b) return -1;

}

 

let arr = [ 1, 2, 15 ];

 

arr.sort(compareNumeric);

 

alert(arr);  // 1, 2, 15

 

arr.sort( (a, b) => a - b );

 

let countries = ['Österreich', 'Andorra', 'Vietnam'];

 

alert( countries.sort( (a, b) => a > b ? 1 : -1) ); // Andorra, Vietnam, Österreich (wrong)

 

let arr = [1, 2, 3, 4, 5];

arr.reverse();

 

alert( arr ); // 5,4,3,2,1

 

let names = 'Bilbo, Gandalf, Nazgul';

 

let arr = names.split(', ');

 

for (let name of arr) {

  alert( `A message to ${name}.` );

}

 

let arr = 'Bilbo, Gandalf, Nazgul, Saruman'.split(', ', 2);

 

alert(arr); // Bilbo, Gandalf

 

let str = "test";

 

alert( str.split('') ); // t,e,s,t

let arr = ['Bilbo', 'Gandalf', 'Nazgul'];

 

let str = arr.join(';'); // glue the array into a string using ;

 

alert( str ); // Bilbo;Gandalf;Nazgul

 

let value = arr.reduce(function(accumulator, item, index, array) {

  // ...

}, [initial]);

 

let arr = [1, 2, 3, 4, 5];

 

let result = arr.reduce((sum, current) => sum + current, 0);

 

alert(result); // 15

 

let arr = [];

 

// Error: Reduce of empty array with no initial value

// if the initial value existed, reduce would return it for the empty arr.

arr.reduce((sum, current) => sum + current);

 

let army = {

  minAge: 18,

  maxAge: 27,

  canJoin(user) {

    return user.age >= this.minAge && user.age < this.maxAge;

  }

};

 

let users = [

  {age: 16},

  {age: 20},

  {age: 23},

  {age: 30}

];

 

// find users, for who army.canJoin returns true

let soldiers = users.filter(army.canJoin, army);

 

alert(soldiers.length); // 2

alert(soldiers[0].age); // 20

alert(soldiers[1].age); // 23

 

 

 

A cheat sheet of array methods:

  • To add/remove elements:
      • push(...items) – adds items to the end,
      • pop() – extracts an item from the end,
      • shift() – extracts an item from the beginning,
      • unshift(...items) – adds items to the beginning.
      • splice(pos, deleteCount, ...items) – at index pos delete deleteCount elements and insert items.
      • slice(start, end) – creates a new array, copies elements from position start till end (not inclusive) into it.
      • concat(...items) – returns a new array: copies all members of the current one and adds items to it. If any of items is an array, then its elements are taken.
  • To search among elements:
      • indexOf/lastIndexOf(item, pos) – look for item starting from position pos, return the index or -1 if not found.
      • includes(value) – returns true if the array has value, otherwise false.
      • find/filter(func) – filter elements through the function, return first/all values that make it return true.
      • findIndex is like find, but returns the index instead of a value.
  • To iterate over elements:
      • forEach(func) – calls func for every element, does not return anything.
  • To transform the array:
      • map(func) – creates a new array from results of calling func for every element.
      • sort(func) – sorts the array in-place, then returns it.
      • reverse() – reverses the array in-place, then returns it.
      • split/join – convert a string to array and back.
      • reduce(func, initial) – calculate a single value over the array by calling func for each element and passing an intermediate result between the calls.
  • Additionally:
      • Array.isArray(arr) checks arr for being an array.

 

 

Interlinked objects

 
function marry(man, woman) {
  woman.husband = man;
  man.wife = woman;
 
  return {
    father: man,
    mother: woman
  }
}
 
let family = marry({
  name: "John"
}, {
  name: "Ann"
});

 

Function marry “marries” two objects by giving them references to each other and returns a new object that contains them both.

The resulting memory structure:

As of now, all objects are reachable.

Now let’s remove two references:

delete family.father;
delete family.mother.husband;

 

It’s not enough to delete only one of these two references, because all objects would still be reachable.

But if we delete both, then we can see that John has no incoming reference any more:

Outgoing references do not matter. Only incoming ones can make an object reachable. So, John is now unreachable and will be removed from the memory with all its data that also became unaccessible.

After garbage collection:

Unreachable island

 

let user = {

  name: "John",

  age: 30,

 

  sayHi() {

    alert( user.name ); // leads to an error

  }

 

};

 

 

let admin = user;

user = null; // overwrite to make things obvious

 

admin.sayHi(); // Whoops! inside sayHi(), the old name is used! error!

 

let user = { name: "John" };

let admin = { name: "Admin" };

 

function sayHi() {

  alert( this.name );

}

 

// use the same function in two objects

user.f = sayHi;

admin.f = sayHi;

 

// these calls have different this

// "this" inside the function is the object "before the dot"

user.f(); // John  (this == user)

admin.f(); // Admin  (this == admin)

 

admin['f'](); // Admin (dot or square brackets access the method – doesn't matter)

 

Arrow functions are special: they don’t have their “own” this. If we reference this from such a function, it’s taken from the outer “normal” function.

For instance, here arrow() uses this from the outer user.sayHi() method:

 

 

let user = {

  firstName: "Ilya",

  sayHi() {

    let arrow = () => alert(this.firstName);

    arrow();

  }

};

 

user.sayHi(); // Ilya

 

function makeUser() {

  return {

    name: "John",

    ref: this

  };

};

 

let user = makeUser();

 

alert( user.ref.name ); // Error: Cannot read property 'name' of undefined

 

function makeUser() {

  return {

    name: "John",

    ref() {

      return this;

    }

  };

};

 

let user = makeUser();

 

alert( user.ref().name ); // John

 

Chaining

There’s a ladder object that allows to go up and down:

 

let ladder = {

  step: 0,

  up() {

    this.step++;

    return this;

  },

  down() {

    this.step--;

    return this;

  },

  showStep() {

    alert( this.step );

    return this;

  }

}

 

Now, if we need to make several calls in sequence, can do it like this:

 

 

ladder.up();

ladder.up();

ladder.down();

ladder.showStep(); // 1

ladder.up().up().down().showStep(); // 1

 

 

Modify the code of up, down and showStep to make the calls chainable, like this:

 

 

function User(name) {

  this.name = name;

  this.isAdmin = false;

}

 

let user = new User("Jack");

 

When a function is executed with new, it does the following steps:

  1. A new empty object is created and assigned to this.
  2. The function body executes. Usually it modifies this, adds new properties to it.
  3. The value of this is returned.

 

 

 

function User(name) {

  // this = {};  (implicitly)

 

  // add properties to this

  this.name = name;

  this.isAdmin = false;

 

  // return this;  (implicitly)

}

 

 

function User() {

  this.name = ‘saravan’

}

 

// without "new":

User(); // not possible without new

 

// with "new":

new User();

 

Now you can do without new

 

function User(name) {

  if (!new.target) { // if you run me without new

    return new User(name); // ...I will add new for you

  }

 

  this.name = name;

}

 

let john = User("John"); // redirects call to new User

 

function BigUser() {

 

  this.name = "John";

 

  return { name: "Godzilla" };  // <-- returns this object

}

 

new BigUser().name

 

By the way, we can omit parentheses after new, if it has no arguments:

 

let user = new User; // <-- no parentheses

// same as

let user = new User();

 

Methods in constructor

 

function User(name) {

  this.name = name;

 

  this.sayHi = function() {

    console.log( "My name is: " + this.name );

  };

}

 

function User(name) {

  name,

 

  sayHi = ()  {

    console.log( "My name is: " + this.name );

  };

}

 

const User =  {

        name : '',

        sayHi : function () {

                console.log('Hi')

    }

}

 

const User2 =  {

        name : '',

        sayHi : () => {

                console.log('Hi')

    }

}

 

 

 

let user = { name: "John" };

 

let permissions1 = { canView: true };

let permissions2 = { canEdit: true };

 

// copies all properties from permissions1 and permissions2 into user

Object.assign(user, permissions1, permissions2);

 

// now user = { name: "John", canView: true, canEdit: true }

 

If the copied property name already exists, it gets overwritten:

 

let user = { name: "John" };

 

Object.assign(user, { name: "Pete" });

 

alert(user.name); // now user = { name: "Pete" }

 

We also can use Object.assign to replace for..in loop for simple cloning:

 

let user = {

  name: "John",

  age: 30

};

 

let clone = Object.assign({}, user);

 

DANGER

 

let user = {

  name: "John",

  sizes: {

    height: 182,

    width: 50

  }

};

 

let clone = Object.assign({}, user);

 

alert( user.sizes === clone.sizes ); // true, same object

 

// user and clone share sizes

user.sizes.width++;       // change a property from one place

alert(clone.sizes.width); // 51, see the result from the other one

 

 

let john = { name: "John" };

 

// the object can be accessed, john is the reference to it

 

// overwrite the reference

john = null;

 

// the object will be removed from memory

 

let john = { name: "John" };

 

let array = [ john ];

 

john = null; // overwrite the reference

 

// john is stored inside the array, so it won't be garbage-collected

// we can get it as array[0]

 

let john = { name: "John" };

 

let map = new Map();

map.set(john, "...");

 

john = null; // overwrite the reference

 

// john is stored inside the map,

// we can get it by using map.keys()

 

let weakMap = new WeakMap();

 

let obj = {};

 

weakMap.set(obj, "ok"); // works fine (object key)

 

// can't use a string as the key

weakMap.set("test", "Whoops"); // Error, because "test" is not an object

 

let john = { name: "John" };

 

let weakMap = new WeakMap();

weakMap.set(john, "...");

 

john = null; // overwrite the reference

 

// john is removed from memory!

 

// 📁 visitsCount.js

let visitsCountMap = new Map(); // map: user => visits count

 

// increase the visits count

function countUser(user) {

  let count = visitsCountMap.get(user) || 0;

  visitsCountMap.set(user, count + 1);

}

 

// 📁 main.js

let john = { name: "John" };

 

countUser(john); // count his visits

 

// later john leaves us

john = null;

 

 

Now john object should be garbage collected, but remains in memory, as it’s a key in visitsCountMap.

 

We need to clean visitsCountMap when we remove users, otherwise it will grow in memory indefinitely. Such cleaning can become a tedious task in complex architectures.

We can avoid it by switching to WeakMap instead:

 

 

// 📁 visitsCount.js

let visitsCountMap = new WeakMap(); // weakmap: user => visits count

 

// increase the visits count

function countUser(user) {

  let count = visitsCountMap.get(user) || 0;

  visitsCountMap.set(user, count + 1);

}

 

// 📁 cache.js

let cache = new Map();

 

// calculate and remember the result

function process(obj) {

  if (!cache.has(obj)) {

    let result = /* calculations of the result for */ obj;

 

    cache.set(obj, result);

  }

 

  return cache.get(obj);

}

 

// Now we use process() in another file:

 

// 📁 main.js

let obj = {/* let's say we have an object */};

 

let result1 = process(obj); // calculated

 

// ...later, from another place of the code...

let result2 = process(obj); // remembered result taken from cache

 

// ...later, when the object is not needed any more:

obj = null;

 

alert(cache.size); // 1 (Ouch! The object is still in cache, taking memory!)

 

or multiple calls of process(obj) with the same object, it only calculates the result the first time, and then just takes it from cache. The downside is that we need to clean cache when the object is not needed any more.

If we replace Map with WeakMap, then this problem disappears: the cached result will be removed from memory automatically after the object gets garbage collected.

 

 

 

let visitedSet = new WeakSet();

 

let john = { name: "John" };

let pete = { name: "Pete" };

let mary = { name: "Mary" };

 

visitedSet.add(john); // John visited us

visitedSet.add(pete); // Then Pete

visitedSet.add(john); // John again

 

// visitedSet has 2 users now

 

// check if John visited?

alert(visitedSet.has(john)); // true

 

// check if Mary visited?

alert(visitedSet.has(mary)); // false

 

john = null;

 

// visitedSet will be cleaned automatically

 

 

 

The most notable limitation of WeakMap and WeakSet is the absence of iterations, and inability to get all current content.

 

// the symbolic property is only known to our code

let isRead = Symbol("isRead");

messages[0][isRead] = true;

 

Now third-party code probably won’t see our extra property.

 

 

 

Return Response From Asynchronous Call Using jQuery AJAX

 

$(function(){

    $('#btnjQueryAjax').click(function(){

        $.ajax({

            url : 'http://jsonplaceholder.typicode.com/users',

            type: 'GET',

            success: function(response) {

                $('#divResult').html(JSON.stringify(response))

            },

            error : function(error) {

                console.log('error is ', error)

            }

        })

    })

})

 

/* helper.js */

 

const helper = (function(){

    function getPhotos(){

        return fetch('https://jsonplaceholder.typicode.com/photos')

            .then((response) => { return response.json() })

    }

    function getPosts(){

        return fetch('https://jsonplaceholder.typicode.com/posts')

            .then((response) => { return response.json() })

    }

    return {

        getPhotos,

        getPosts

    }

})();

 

/* app.js */

 

helper.getPhotos()

.then(function(response){

    console.log(response);

    return helper.getPosts()

})

.then(function(response){

    console.log(response);

})

.catch(function(error){

    console.log(`Error occured ${error}`);

})

 

async function callAPI(){

    let photos = helper.getPhotos();

    let posts = helper.getPosts();

    let [photosResponse, postsResponse] = [await photos, await posts];

    console.log(photosResponse, postsResponse)

}

callAPI();

 

 

 

  • Focus on plain Vanilla Javascript. Knowledge of a framework - React/Angular is always secondary.
  • Practice problems around core Javascript concepts - Hoisting, closures, functions, arrays, object, event loops, timers. Learn how to apply them.
  • Have a knowledge of Javascript patterns.
  • Practice plugin development - how can you create your own Javascript library - modals, accordions etc.
  • Know the ecosystem - environment where Javascript runs - browser/server. How browsers work? How they render pages?
  • Javascript tooling - webpack, bower, rollup ... what they exactly do, why do we need them
  • Testing in Javascript - Most ignored but one of the most important topics.
  • Performance - Making websites fast, making your code production ready, techniques like debouncing/throttling, lazy loading, virtualisation etc.
  • Utility functions

 

 

function convertToRoman(num) {

    var roman = {

      M: 1000,

      CM: 900,

      D: 500,

      CD: 400,

      C: 100,

      XC: 90,

      L: 50,

      XL: 40,

      X: 10,

      IX: 9,

      V: 5,

      IV: 4,

      I: 1

    };

    var str = '';

 

    for (var i of Object.keys(roman)) {

      var q = Math.floor(num / roman[i]);

      num -= q * roman[i];

      str += i.repeat(q);

    }

 

    return str;

  }

 

   

  var romanMatrix = [

    [1000, 'M'],

    [900, 'CM'],

    [500, 'D'],

    [400, 'CD'],

    [100, 'C'],

    [90, 'XC'],

    [50, 'L'],

    [40, 'XL'],

    [10, 'X'],

    [9, 'IX'],

    [5, 'V'],

    [4, 'IV'],

    [1, 'I']

  ];

 

  function convertToRoman(num) {

    if (num === 0) {

      return '';

    }

    for (var i = 0; i < romanMatrix.length; i++) {

      if (num >= romanMatrix[i][0]) {

        return romanMatrix[i][1] + convertToRoman(num - romanMatrix[i][0]);

      }

    }

  }

 

 

  Number.fromRoman = function (roman, accept) {

      var s = roman.toUpperCase().replace(/ +/g, ''),

          L = s.length, sum = 0, i = 0, next, val,

          R = { M: 1000, D: 500, C: 100, L: 50, X: 10, V: 5, I: 1 };

 

      function fromBigRoman(rn) {

          var n = 0, x, n1, S, rx =/(\(*)([MDCLXVI]+)/g;

 

          while ((S = rx.exec(rn)) != null) {

              x = S[1].length;

              n1 = Number.fromRoman(S[2])

              if (isNaN(n1)) return NaN;

              if (x) n1 *= Math.pow(1000, x);

              n += n1;

          }

          return n;

      }

 

      if (/^[MDCLXVI)(]+$/.test(s)) {

          if (s.indexOf('(') == 0) return fromBigRoman(s);

 

          while (i < L) {

              val = R[s.charAt(i++)];

              next = R[s.charAt(i)] || 0;

              if (next - val > 0) val *= -1;

              sum += val;

          }

          if (accept || sum.toRoman() === s) return sum;

      }

      return NaN;

  };

 

  function convert(num) {

    if(num < 1){ return "";}

    if(num >= 40){ return "XL" + convert(num - 40);}

    if(num >= 10){ return "X" + convert(num - 10);}

    if(num >= 9){ return "IX" + convert(num - 9);}

    if(num >= 5){ return "V" + convert(num - 5);}

    if(num >= 4){ return "IV" + convert(num - 4);}

    if(num >= 1){ return "I" + convert(num - 1);}  

  }

  console.log(convert(39));

  //Output: XXXIX

  This will only support numbers 1-40, but it can easily be extended by following the pattern.

 

https://stackoverflow.com/questions/9083037/convert-a-number-into-a-roman-numeral-in-javascript

https://www.w3resource.com/javascript-exercises/javascript-math-exercise-21.php

 

How to check User online or offline status

 

https://www.youtube.com/watch?v=yqNgZDIgIeM

 

 

 

 

 

 

 

 

 

console.log(Array.from({ length: 10 }, (v, k) => k + 1))

 

// http://dmitripavlutin.com/javascript-array-from-applications/

 

const someNumbers = { '0': 10, '1': 15, length: 2 }

 

Array.from(someNumbers, value => value * 2) // => [20, 30]

 

const length = 3

const init = 0

const result = Array.from({ length }, () => init)

 

result // => [0, 0, 0]

 

const length = 3

const init = 0

const result = Array(length).fill(init)

 

fillArray2(0, 3) // => [0, 0, 0]

 

 

zip tests

 

https://medium.com/@tdillusionisme/javascript-iife-and-why-to-use-them-cbdff335f565

 

IIFE

 

IIFE stands for ‘Immediately Invoked Function Expression’

Self-Executing Anonymous Function

 

Reduces the global variable namespace pollution and improves performance.

See the difference below

 

 

<script>

      var glob_a = 10;

      setTimeout(() => console.log(glob_a),1000);          //30

    </script>

    <script>

      var glob_a = 20;

      setTimeout(() => console.log(glob_a),1000);          //30

    </script>

    <script>

      var glob_a = 30;

      setTimeout(() => console.log(glob_a),1000);          //30

    </script>

 

<script>

      (function(){

          var glob_a = 10;

          setTimeout(() => console.log(glob_a),1000);     //10

      })();

    </script>

    <script>

      (function(){

          var glob_a = 20;

          setTimeout(() => console.log(glob_a),1000);     //20

      })();

    </script>

    <script>

      (function(){

          var glob_a = 30;

          setTimeout(() => console.log(glob_a),1000);     //30

      })();

    </script>

 

 

 

Hide 🙈 all console logs in production with just 3 lines of code

 

if (env === 'production') {

    console.log = function () {};

}



if (env === 'production') {

  const noop = () => {}

  ['assert', 'clear', 'count', 'debug', 'dir', 'dirxml', 'error',

    'exception', 'group', 'groupCollapsed', 'groupEnd', 'info', 'log',

    'markTimeline', 'profile', 'profileEnd', 'table', 'time', 'timeEnd',

    'timeline', 'timelineEnd', 'timeStamp', 'trace', 'warn',

  ].forEach((method) => {

    window.console[method] = noop

  })

}

 

 

ES6 Class Multiple inheritance

 

https://stackoverflow.com/questions/29879267/es6-class-multiple-inheritance/45332959

 

// base class

class A {  

    foo() {

        console.log(`from A -> inside instance of A: ${this instanceof A}`);

    }

}

 

// B mixin, will need a wrapper over it to be used

const B = (B=> class extends B {

    foo() {

        if (super.foosuper.foo(); // mixins don't know who is super, 

                  guard against not having the method

        console.log(`from B -> inside instance of B: ${this instanceof B}`);

    }

};

 

// C mixin, will need a wrapper over it to be used

const C = (C=> class extends C {

    foo() {

        if (super.foosuper.foo(); // mixins don't know who is super, 

                  guard against not having the method

        console.log(`from C -> inside instance of C: ${this instanceof C}`);

    }

};

 

// D class, extends A, B and C, preserving composition and super method

class D extends C(B(A)) {  

    foo() {

        super.foo();

        console.log(`from D -> inside instance of D: ${this instanceof D}`);

    }

}

 

// E class, extends A and C

class E extends C(A) {

    foo() {

        super.foo();

        console.log(`from E -> inside instance of E: ${this instanceof E}`);

    }

}

 

// F class, extends B only

class F extends B(Object) {

    foo() {

        super.foo();

        console.log(`from F -> inside instance of F: ${this instanceof F}`);

    }

}

 

// G class, C wrap to be used with new decorator, pretty format

class G extends C(Object) {}

 

 

 

 

 

class Nose {

  constructor() {

    this.booger = 'ready'

  }

 

  pick() {

    console.log('pick your nose')

  } 

}

 

class Ear {

  constructor() {

    this.wax = 'ready'

  }

 

  dig() {

    console.log('dig in your ear')

  } 

}

 

class Gross extends Classes([Nose,Ear]) {

  constructor() {

    super();

    this.gross = true;

  }

}

 

function Classes(bases) {

  class Bases {

    constructor() {

      bases.forEach(base => Object.assign(thisnew base()));

    }

  }

  bases.forEach(base => {

    base.prototype

    .properties()

    .filter(prop => prop != 'constructor')

    .forEach(prop => Bases.prototype[prop] = base.prototype[prop])

  })

  return Bases;

}

 

// test it

function dontLook() {

  var grossMan = new Gross();

  grossMan.pick(); // eww

  grossMan.dig();  // yuck!

}

 

Well Object.assign gives you the possibility to do something close albeit a bit more like composition with ES6 classes.

 

class Animal {

    constructor(){ 

     Object.assign(thisnew Shark()) 

     Object.assign(thisnew Clock()) 

  }

}

 

class Shark {

  // only what's in constructor will be on the object, ence the weird this.bite = this.bite.

  constructor(){ this.color = "black"this.bite = this.bite }

  bite(){ console.log("bite") }

  eat(){ console.log('eat') }

}

 

class Clock{

  constructor(){ this.tick = this.tick; }

  tick(){ console.log("tick"); }

}

 

let animal = new Animal();

animal.bite();

console.log(animal.color);

animal.tick();

 

I've not seen this used anywhere but it's actually quite useful. You can use function shark(){} instead of class but there are advantages of using class instead.

I believe the only thing different with inheritance with extend keyword is that the function don't live only on the prototype but also the object itself.

Thus now when you do new Shark() the shark created has a bite method, while only its prototype has a eat method

 

https://github.com/latitov/OOP_MI_Ct_oPlus_in_JS

 

 

class Car {

    constructor(brand) {

        this.carname = brand;

    }

    show() {

        return 'I have a ' + this.carname;

    }

}

 

class Asset {

    constructor(price) {

        this.price = price;

    }

    show() {

        return 'its estimated price is ' + this.price;

    }

}

 

class Model_i1 {        // extends Car 

    // and Asset (just a comment for ourselves)

    //

    constructor(brandpriceusefulness) {

        specialize_with(thisnew Car(brand));

        specialize_with(thisnew Asset(price));

        this.usefulness = usefulness;

    }

    show() {

        return Car.prototype.show.call(this) + ", " + 

        Asset.prototype.show.call(this) + ", Model_i1";

    }

}

 

 

function specialize_with(oS) {

    for (var prop in S) {

        o[prop] = S[prop];

    }

}

 

 

mycar = new Model_i1("Ford Mustang""$100K"16);

 

 

 

 

 

 

 

 

 

 

 

https://aparnajoshi.netlify.app/object-oriented-programming-with-javascript

 

function Vehicle(name, cost, engineType) {

    this.name = name || '';

    this.cost = cost || 0;

    this.engineType = engineType || 'petrol';

 

}

 

Vehicle.prototype = {

    constructor: Vehicle,

    getEngineType: function ()  {

        return this.engineType;

    },

    calculateEmi: function ()  {

        return this.cost * 0.12;

    },

    setEngineType: function (type)  {

        this.engineType = type;

    }

}

 

var vehicle1 = new Vehicle('Lamborghini Gallardo', 20000, 'petrol');

console.log(vehicle1.getEngineType()); // petrol

vehicle1.setEngineType('diesel');

console.log(vehicle1.getEngineType()); // diesel

 

function Car(model, hasFuel, color, name, cost, engineType ) {

    this.model = model || '';

    this.hasFuel = hasFuel || false;

    this.color = color || '';

    this.name = name || '';

    this.cost = cost || 0;

    this.engineType = engineType || 'petrol';

}

 

OR

 

function Car(model, hasFuel, color, name, cost, engineType ) {

    this.model = model || '';

    this.hasFuel = hasFuel || false;

    this.color = color || '';

    Vehicle.call(this, [name, cost, engineType]);

}

 

 

Car.prototype = new Vehicle();

// Car.prototype = Object.create( Vehicle.prototype );

// This works too

Car.prototype.constructor = Car;

 

var lambo = new Car('gallardo', true, 'yellow', 'Lamborighini', 20000, 'petrol');

console.log(lambo.calculateEmi()); // 2400

 

Class-based inheritance and encapsulation: ES6

 

class Vehicle {

    constructor(name, cost, engineType){

        this.name = name || '';

        this.cost = cost || 0;

        this.engineType = engineType || 'petrol';

    }

 

    getEngineType()  {

        return this.engineType;

    }

 

    calculateEmi()  {

        return this.cost * 0.12;

    }

 

    setEngineType(type)  {

        this.engineType = type;

    }

}

 

class Car extends Vehicle{

    constructor(model, hasFuel, color, name, cost, engineType) {

        super(name, cost, engineType);

        this.model = model || '';

        this.hasFuel = hasFuel || false;

        this.color = color || '';

    }

}

 

var lambo = new Car('gallardo', true, 'yellow', 'Lamborighini', 20000, 'petrol');

console.log(lambo.calculateEmi()); // 2400

 

prototypes have its drawbacks. Any change in one of the properties will be reflected in all the objects.

 

function Apple(name, color) {

    this.name = name;

    this.color = color

}

 

Apple.prototype.value = 20;

 

var apple1 = new Apple("Apple", "Red");

var apple2 = new Apple("Apple2", "Wheatish Red");

 

console.log(apple1.name); // Apple

console.log(apple1.value); // 20

console.log(apple2.value); // 20

 

Apple.prototype.value = 40;

console.log(apple1.value); // 40

console.log(apple2.value); // 40

 

apple1.value = 30;

console.log(apple1.value); // 30

console.log(apple2.value); // 40

 

 

The context of this can be changed

  • Borrowing a method that uses this
  • Assign a method that uses this
  • Callback function using this.
  • this used inside a closure.

 

var person1 = {

    firstName: "Jensen",

    lastName: "Ackles",

    showFullName: function () {

        console.log(this.firstName + " " + this.lastName);

    }

}

 

var person2 = {

    firstName: "Dean",

    lastName: "Winchester",

}

 

person1.showFullName (); // Jensen Ackles - this refers to person1 object

person1.showFullName.apply(person2); // Dean Winchester - this refers to person2 object

 

forced the context of this to person2

this when borrowing methods:

 

var person1 = {

    firstName: "Jensen",

    lastName: "Ackles",

    showFullName: function () {

        return this.firstName + " " + this.lastName;

    }

}

 

var person2 = {

    firstName: "Dean",

    lastName: "Winchester",

}

 

person2.fullName = person1.showFullName();

console.log(person2.fullName); // Jensen Ackles - this refers to person1 object

person2.fullName = person1.showFullName.apply(person2);

console.log(person2.fullName); // Dean Winchester - this refers to person2 object

 

var person = {

    firstName: "Jensen",

    lastName: "Ackles",

    fullName: function () {

        return this.firstName + " " + this.lastName;

    }

}

 

var showFullName = person.fullName;

console.log(showFullName()); // undefined undefined

 

its context is not set to the global variable. Since the global window object doesn't contain the value of firstName and lastName, they are printed as undefined. To fix this problem, we can set the value of this to a particular object indefinitely using bind:

 

 

var person = {

    firstName: "Jensen",

    lastName: "Ackles",

    fullName: function () {

        return this.firstName + " " + this.lastName;

    }

}

 

var showFullName = person.fullName.bind(person);

console.log(showFullName()); // Jensen Ackles

 

 

this when used inside a method as a callback:

 

 

var person = {

    firstName: "Jensen",

    lastName: "Ackles",

    fullName: function () {

        console.log(this.firstName + " " + this.lastName);

    }

}

 

setTimeout(person.fullName, 1000); // undefined undefined

 

 

The above code works similarly to how the context of this changes when it is assigned to a variable. One can assume that the setTimeOut function has a variable that takes the function as a parameter, and then it executes on the global object. Since the global object doesn't contain the definition to firstName and lastName, the value is printed as undefined.

To fix this, we need to bind the value of this to the object on which it should be applied. This is a pattern most commonly seen when we are defining callback functions to the javascript events.

 

 

setTimeout(person.fullName.bind(person), 1000); // Jensen Ackles

 

this when used inside a closure:

 

Another instance when the value of this is misunderstood is when this is used inside closures.

 

var person = {

    fullName: "Jensen Ackles",

    getDetails: function () {

        var closureFunction  =  function() {

            console.log(this.fullName); // undefined

            console.log(this); // global window object

        }

        closureFunction();

    }

}

 

person.getDetails();

 

The value of this doesn't refer to the person object, rather it refers to the global window object. We have two ways of mitigating this problem:

 

1. Assign the value of this to an explicit variable, and then use that variable to access the properties.

 

var person = {

    fullName: "Jensen Ackles",

    getDetails: function () {

        var personObj =  this;

        var closureFunction  =  function() {

            console.log(personObj.fullName); // Jensen Ackles

            console.log(personObj); // person Object

        }

        closureFunction();

    }

}

 

person.getDetails();

 

2. Use arrow function provided by **ES6: Arrow function preserves the context of this.**

 

var person = {

    fullName: "Jensen Ackles",

    getDetails: function () {

        var closureFunction  = () => {

            console.log(this.fullName); // Jensen Ackles

            console.log(this); // person Object

        }

        closureFunction();

    }

}

 

person.getDetails();

 

This article has aimed at providing a detailed understanding of how this is used in javascript and has warned about the pitfalls which can be avoided while using this. Using javascript's apply, call, bind and arrow functions, we can control the value of this to meet our needs. As a final note, please remember that the value of this is usually the object on which the function is called.

 

 

"ReferenceError: full_name is not defined
    at fefezaq.js:10:38

 

 

What are the differences/advantages between these functions?

 

 

Arrow function dosent have its own this, it consider parents this.

The first one is initialized and hoisted immediately the first time js engine goes through the code. The second one is not hoisted and not initialised already at the beginning. Therefor you can write the first one at any place, but the second one you need to position in your code before it is called. Also the second one always hase lexical scope. So the this keyword will not return the object on which the function is called but refers to the nearest scope.

If we use arrow function then we don't have to explicitly bind the function.

 

https://www.designmycodes.com/examples/a-perfect-guide-for-cracking-a-javascript-interview-a-developers-perspective.html?fbclid=IwAR09rNwMPZ5hfVbtvvWaMG1egTZKGEbDJkD2zDYoK_UJXz4wtGO5M1_oNG4

 

var mathLib = {

    pi: 3.14,

    area: function(r) {

        return this.pi * r * r;

    },

    circumference: function(r) {

        return 2 * this.pi * r;

    }

};

 

mathLib.area(2); // 12.56

 

mathLib.area.call({pi: 3.14159}, 2); // takes new pi value on the ply

// that is the beauty of call

 

var cylinder = {

    pi: 3.14,

    volume: function(rh) {

        return this.pi * r * r * h;

    }

};

 

cylinder.volume.call({pi: 3.14159}, 26);

75.39815999999999

 

cylinder.volume.apply({pi: 3.14159}, [26]);

75.39815999999999

 

 

What is the use of Bind? It allows us to inject a context into a function which returns a new function with updated context. It means this variable will be user supplied variable. This is very useful while working with JavaScript events.

 

•   Global scope

•   Local Scope/Function scope

•   Block scope(Introduced in ES6)

 

pi = 3.14;

function circumference(radius) {    

    pi = 3.14159;

    console.log(2 * pi * radius); // Prints "12.56636" not "12.56"

}circumference(2);

 

var a = 10;

 

function Foo() {

  if (true) {

    let a = 4;

  }

 

  alert(a); // alerts '10' because the 'let' keyword

}Foo();

 

Closure

 

JavaScript closure is a function that returns another function.

 

Write a design that takes a string and returns a character at a time. If the new string is given, it should replace the old one. It is simply called a generator.

 

function generator(input) {

    var index = 0;

    return {

         next: function() {

                 if (index < input.length) {

                      index += 1;

                      return input[index - 1];

                 }

                 return "";

         } 

    }

}



var mygenerator = generator("boomerang");

mygenerator.next(); // returns "b"

mygenerator.next() // returns "o"mygenerator = generator("toon");

mygenerator.next(); // returns "t"

 

function Foo(){

    console.log(this.a);

  }

 

var food = {a: "Magical this"};

 

Foo.call(food); // food is this

 

Object.seal is slightly different from the freeze. It allows configurable properties but won’t allow new property addition or deletion or properties.

 

 

var marks = {physics: 98maths:95chemistry: 91};

Object.seal(marks);

delete marks.chemistry// returns false as operation failed

marks.physics = 95// Works!

marks.greek = 86// Will not add a new property

 

Object.freeze allows us to freeze an object so that existing properties cannot be modified.

 

 

var marks = {physics: 98maths:95chemistry: 91};

finalizedMarks = Object.freeze(marks);

finalizedMarks["physics"] = 86// throws error in strict mode

console.log(marks); // {physics: 98, maths: 95, chemistry: 91}

 

Understand the callbacks and promises well

 

regex

 

var re = /ar/;

var re = new RegExp('ar'); // This too works

re.exec("car"); // returns ["ar", index: 1, input: "car"]

re.exec("cab"); // returns 

 

/* Character class */

var re1 = /[AEIOU]/;

re1.exec("Oval"); // returns ["O", index: 0, input: "Oval"]

re1.exec("2456"); // 

var re2 = /[1-9]/;

re2.exec('mp4'); // returns ["4", index: 2, input: "mp4"]/* Characters */var re4 = /\d\D\w/;

re4.exec('1232W2sdf'); // returns ["2W2", index: 3, input: "1232W2sdf"]

re4.exec('W3q'); // returns 

/* Boundaries */

var re5 = /^\d\D\w/;

re5.exec('2W34'); // returns ["2W3", index: 0, input: "2W34"]

re5.exec('W34567'); // returns 

var re6 = /^[0-9]{5}-[0-9]{5}-[0-9]{5}$/;

re6.exec('23451-45242-99078'); // returns ["23451-45242-99078", index: 0, input: "23451-45242-99078"]

re6.exec('23451-abcd-efgh-ijkl'); // returns 

/* Quantifiers */

var re7 = /\d+\D+$/;

re7.exec('2abcd'); // returns ["2abcd", index: 0, input: "2abcd"]

re7.exec('23'); // returns 

 

re7.exec('2abcd3'); // returns 

var re8 = /<([\w]+).*>(.*?)<\/\1>/;

re8.exec('<p>Hello JS developer</p>'); //returns  "<p>Hello JS developer</p>"

 

 

Understand Error handling patterns

 

$("button").click(function(){

    $.ajax({url: "user.json"success: function(result){

        updateUI(result["posts"]);

    }});

});

 

 

Hoisting

Hoisting is a process of pushing the declared variables to the top of the program while running it. 

 

Event Bubbling

 

Event bubbling and capturing are two ways of event propagation in the HTML DOM API when an event occurs in an element inside another element, and both elements have registered a handler for that event. The event propagation mode determines in which order the elements receive the event.”

 

With bubbling, the event is first captured and handled by the innermost element and then propagated to outer elements. With capturing, the process is in reverse. We usually attach an event to a handler using the addEventListener function.

 

addEventListener("click", handler, useCapture=false)

 

The third argument useCapture is the key. The default value is false. So, it will be a bubbling model where the event is handled by the innermost element first and it propagates outwards till it reaches the parent element. If that argument is true, it is capturing model.

 

 

When You Should Use JavaScript Maps over Objects

  • Only strings or symbols can be used as keys
  • Own object properties might collide with property keys inherited from the prototype (e.g. toString, constructor, etc).
  • Objects cannot be used as keys

These limitations are solved by maps.

Moreover, maps provide benefits like being iterators and allowing easy size look-up.Objects are not good for information that’s continually updated, looped over, altered, or sorted.

 

Use objects the vast majority of the time, but if your app needs one of these extra bits of functionality, use map.

 

 

 

What’s a “Closure”?

Every function in JavaScript is a closure!

That means that every function closes over its environment when it’s created.

 

 

because the value is only looked up when its needed, not when the closure is created!

 

Now let's define a closure:

A closure is the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment)

 

 

JavaScript Hoisting