Skip to content

Instantly share code, notes, and snippets.

@deependhamecha
Last active June 20, 2023 09:10
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save deependhamecha/78bcc2dc96f5d7d7056986c06f695ec0 to your computer and use it in GitHub Desktop.
Save deependhamecha/78bcc2dc96f5d7d7056986c06f695ec0 to your computer and use it in GitHub Desktop.
Core JS

Core.js

Versions
1 es5
2 es6
3 es2015
4 es7
5 es2016
6 es2017
7 es2018
8 es2019
9 esnext

Different Function declaractions in JS :

function getData() {} // Normal Function

(function() {})(); // Immediate call

var b = function() {}; // function expression

var c = function setData() {}; // named function expression

var d = () => {}; // Arrow function 

Note : All these functions refer to global object(node) / window object(window)

Note : JavaScript functions are executed using the scope they were defined in.

Immediately Call function

var b = function() {
  return 'Hello';
}();

b(); // Not a Function
b // 'Hello'

Above has its own execution context.

If you want to use another context,

name = 'Hey';

(function(name) {
  console.log(name);
}('Hello'));

These both are in different context. Now what if you want to use another.

name = 'Hey';

(function(global, name) {
  console.log(name+" "+global);
}(name, 'Hello'));

Keep a Function but dont call it

If you keep the below code, it will throw an error

function () {
  return 'Hello';
}

So wrap it in a paranthesis,

(function () {
  return 'Hello';
});

If you want to call it, then

(function () {
  return 'Hello';
}());

(function () {
  return 'Hello';
})();

Call and Apply Functions

If you want to change this reference in a function then call the method with call function or apply :

function add(c,d) {
  return this.a + this.b + c + d;
}

var o = { a: 1, b: 2 };

add.call(o, 2, 4); // 9

add.apply(o, [2,4]); // 9

Bind Functions

It creates a clone of the function provided.

Call and Apply functions change this reference of a function during invocation. What if you want to define while declaration ?

** Bind to the rescue **

function d() {
  return this.name;
}

var o = { name : 'Deepen' };

// Create a new method using bind.
// This will copy the function but assigns this to given object reference
var g = d.bind(o);

g(); // Deepen
var dude = function() {
	return this.firstname+ " " + this.lastname;
}.bind(a);

Now, you can also provide additional parameters to bind, which will permanently define those arguments to the called function.

var dude = function(txt) {
	return txt;
}.bind(window, 'My Text');

dude();

Now, check this example,

var dude = function(a,b) {
	return a+b;
}.bind(window, 2);

dude(); // NaN
dude(3); // 5

If you do not provide all arguments to bind, its Okay, however, if pass arguments to calling function, it will apply to next following argument to function parameters.

Object.constructor

All objects will have a constructor property. Objects created without the explicit use of a constructor function (i.e. the object and array literals) will have a constructor property that points to the Fundamental Object constructor type for that object.

var o = {};
o.constructor === Object; // true

var o = new Object;
o.constructor === Object; //true

var a = [];
a.constructor === Array; // true

var a = new Array;
a.constructor === Array //true

var n = new Number(3);
n.constructor === Number; // true

If you ned to know exact Class Type of an Object, use constructor property of the object to determine.

Functions as Constructor

This code ensures function to be always called as Constructor :

function Book(name, year) { 
  if (!(this instanceof Book)) { 
    return new Book(name, year);
  }
  this.name = name;
  this.year = year;
}

Core JavaScript and Prototype (Deprecated)

Unlike Other Programming Languages, JavaScript does not depend on classes for inheritance. Rather it follows a prototype architecture inheritance.

So, how does it work? Well, every object has one property named prototype (proto) which links or points to its parent. It may or may not have a value pointing to another object.

So, when you write:

var myObject = {};

has a property named prototype. In this case, as it is an Object, it points to Object.prototype.

If you want to create an object with no prototype linking to another object (not even Object.prototype) then use following code:

var myObject = Object.create(null);

Object.create() links to another object, in this case, its prototype is set to null (not referencing to anyone).

var d = {}
var e = []
var f = Object.create(null);

console.log(Object.getPrototypeOf(d) === Object.prototype);
console.log(Object.getPrototypeOf(e) === Array.prototype);
console.log(Object.getPrototypeOf(f) === null);

Setting Prototype

It should not be done, as it may cause performance issues.

Creating Properties

For Objects

var myObject = {}

Object.defineProperty(myObject, 'property1', {
  value: 'Deepen',
	configurable: true,
	writable: true,
	enumerable: true
})

console.log(myObject.property1) // Output: Deepen
  • Configurable - It cannot be replaced(i.e. its key cannot be replaced) but its value can be edited if false.
  • Writable - Its value cannot edited if false.
  • Enumerable - It cannot be iterated if false. (for each loop)

We will see each properties in detail, just hang on:

For Arrays

var myObject = []

Object.defineProperty(myObject, 0, {
  value: 'a',
	configurable: true,
	writable: true,
	enumerable: true
})

Object.defineProperty(myObject, 1, {
  value: 'b',
	configurable: true,
	writable: true,
	enumerable: true
})

Object.defineProperty(myObject, 2, {
  value: 'c',
	configurable: true,
	writable: true,
	enumerable: true
})

Now, when yo do:

console.log(myObject); // [ 'a', 'b', 'c' ]
for(var obj in myObject) {
  console.log(obj) // 0 1 2
}
Enumerable

However, when you change enumerable property to false (myObject[1]), see what happens:

var myObject = []

Object.defineProperty(myObject, 0, {
  value: 'a',
	configurable: true,
	writable: true,
	enumerable: true
})

Object.defineProperty(myObject, 1, {
  value: 'b',
	configurable: true,
	writable: true,
	enumerable: false
})

Object.defineProperty(myObject, 2, {
  value: 'c',
	configurable: true,
	writable: true,
	enumerable: true
})

Now, when yo do:

console.log(myObject); // [ 'a', [1]: 'b', 'c' ]
for(var obj in myObject) {
  console.log(obj) // 0 2
}

It does not allow to enumerate(iterate via for each loop), however you can use for loop and iterate and point to each array index like this:

for(var i=0;i<myObject.length;i++) {
  console.log(myObject[i]); // 0 1 2
}

Now, what if you change the key:

var myObject = []

Object.defineProperty(myObject, 0, {
  value: 'a',
	configurable: true,
	writable: true,
	enumerable: true
})

Object.defineProperty(myObject, 11, {
  value: 'b',
	configurable: true,
	writable: true,
	enumerable: false
})

Object.defineProperty(myObject, 2, {
  value: 'c',
	configurable: true,
	writable: true,
	enumerable: true
})
console.log(myObject); // [ 'a', , 'c', , , , , , , , , [11]: 'b' ]
for(var obj in myObject) {
  console.log(obj) // 0 2
}

However, you can also add string like this '11' or '2' but you cannot add strings which cannot be converted to number like 'key1' or 'key2'.

Writable
myObject[2] = 'Boo'
console.log(myObject[2]) // Output: Boo

Now, this time change value of myObject[2]'s property writable to false.

myObject[2] = 'Boo'
console.log(myObject[2]) // Output: b

Writable false makes it constant.

Configurable
console.log(delete myObject[0]); // Will Delete Element on index 0

OR

console.log(delete myObject.property1) // Will Delete property1 of the Element

&

Object.defineProperty(myObject, 0, {
  value: 'a',
	configurable: true,
	writable: true,
	enumerable: **false**
})

If you redefine same property or index, it will replace old one with new property value of enumerable, writeable or simply pu t it, it will allow to replace and delete the key or index but if you make configurable to false then and you define same property, it wont allow you set.

isPrototypeOf

function A () {}
function B () {}
function C () {}

B.prototype = Object.create(A.prototype);
C.prototype = Object.create(B.prototype);

var c = new C();

console.log(C.prototype.isPrototypeOf(c)); // true
console.log(C.prototype.isPrototypeOf(c)); // true
console.log(c instanceof A); // true
console.log(B.prototype.isPrototypeOf(c)); // true
console.log(A.prototype.isPrototypeOf(c)); // true
console.log(Object.prototype.isPrototypeOf(c)); // true

hasOwnProperty

var d = {}
d.name = 'Deepen'
console.log(d.hasOwnProperty(name))

It will only check in d object and not in its prototype. For checking in prototype as well use in operator:

var e = Object.create(d)
console.log('name' in e)

Different way of defining functions

Suppose we two or more functionalities so we can nest like this,

function makeAdder(x) {
  return function(y) {
    return x + y;
  };
}

var add5 = makeAdder(5);
var add10 = makeAdder(10);

console.log(add5(2));  // 7
console.log(add10(2)); // 12

Random Use of Function

function makeSizer(size) {
  return function() {
    document.body.style.fontSize = size + 'px';
  };
}

var size12 = makeSizer(12);
var size14 = makeSizer(14);
var size16 = makeSizer(16);

size12, size14, and size16 are now functions which will resize the body text to 12, 14, and 16 pixels, respectively. We can attach them to buttons (in this case links) as follows:

document.getElementById('size-12').onclick = size12;
document.getElementById('size-14').onclick = size14;
document.getElementById('size-16').onclick = size16;
<a href="#" id="size-12">12</a>
<a href="#" id="size-14">14</a>
<a href="#" id="size-16">16</a>

Private Method in JavaScript

var counter = (function() {
  var privateCounter = 0;
  function changeBy(val) {
    privateCounter += val;
  }
  return {
    increment: function() {
      changeBy(1);
    },
    decrement: function() {
      changeBy(-1);
    },
    value: function() {
      return privateCounter;
    }
  };   
})();

console.log(counter.value()); // logs 0
counter.increment();
counter.increment();
console.log(counter.value()); // logs 2
counter.decrement();
console.log(counter.value()); // logs 1

Closure

function dude() {
	return function(name) {
		console.log('name');
	}
}

dude()('Deepen');
function setLang(lang) {
	return function (name) {
		if(lang == 'en') {
			return 'Hi, '+name;
		} else if(lang == 'it') {
			return 'Bonjure, '+name;
		} else {
			return 'Namaste, '+name;
		}
	}
}

var sayHi = setLang('en');
sayHi('Deepen');

Function Constructors

Constructor in Javascript

function Person(firstname, lastname) {
	this.firstname = firstname;
	this.lastname = lastname;
}

var person1 = new Person('Deepen', 'Dhamecha');
var person2 = new Person('Dilisha', 'Dhamecha');

Person.prototype.getFullName = function() {
	return this.firstname + ' ' + this.lastname;
}



var s = new String('John');
String.prototype.functionName = function() {
	return any;
}

person1.getFullName();
person2.getFullName();

Create empty Object with prototype

var person = {
	this.firstname = 'Deepen;
	this.lastname = 'Dhamecha';
};

var o = Object.create(person);

Now o is empty and its prototype(parent) is person.

Use Strict

Only apply to function

function dude() {
	'use strict';
	var person = {};
	persom.name = 'Deepen';
}

Apply to whole file

'use strict';
var person = {};
persom.name = 'Deepen';

JavaScript Inheritance

JavaScript is a prototypal language, which means that objects inherit directly from other objects.

Actually, JavaScript is conflicted about its prototypal nature. Instead of having objects inherit directly from other objects, an unnecessary level of indirection is inserted such that objects are produced by constructor functions.

When a function object is created, the Function constructor that produces the function object runs some code like this:

this.prototype = {constructor: this};

The new function object is given a prototype property whose value is an object containing a constructor property whose value is the new function object. Every function gets a prototype object because the language does not provide a way of determining which functions are intended to be used as constructors.

JavaScript Modules

This is using default

x.js

export default function xx() {
    return "Hello World!";
}

main.js

import anyName from './x';

console.log(anyName());

When you dont have to use default export, x.js

export function xx() {
    return "Hello World!";
}

main.js

import { anyName } from './x';
console.log(anyName);

As if you are importing one by one.


When you have multiple functions to export,

y.js

export function y1() {
    return "Y1";
}

export function y2() {
    return "Y2";
}

// You can rename anything you would like to rename as the key of this object
export default {
    y5: y1,
    y6: y2
};

main.js

import obj from './y.js';

console.log(obj.y1());
console.log(obj.y2());

Now using es2015 style using require, z.js

function dude() {
    return "Dude";
}

module.exports = dude;

main.js

var d = require('./z');
console.log(d.dude1());

Now using es2015 style using require for multiple modules,

z.js

function dude() {
    return "Dude";
}

function dudex() {
    return "Yo Dude";
}

module.exports = {
    dude1: dude,
    dude2: dudex
}

main.js

var d = require('./z');
console.log(d.dude1());

ES6 Features

Destructing Object

Before ES6

var user = {name: 'Deepen', age: 26};
var name = user.name; // 'Deepen'
var age: user.age; // 26

Using ES6

var { name, age } = {name: 'Deepen', age: 26};
console.log(name); // 'Deepen'
console.log(age); // 26

Before ES6

var user = {name: 'Deepen', age: 26};
var nameX = user.name;
var ageX = user.age;

Using ES6

var user = {name: 'Deepen', age: 26};
var { name:nameX, age:ageX } = user;

If not present then provide default like this:

var user = {name: 'Deepen', age: 26};
var {name:nameX='', age:ageX=1};

Destructing Arrays (Spread Operator)

var dudes = ['John', 'Smith', 'Deepen'];
var [d1, d2] = dudes;
console.log(d1); // 'John'
console.log(d2); // 'Smith'

Provide default value

var dudes = ['John'];
var [d1="Deepen", d2="Smith"] = dudes;
console.log(d1); // 'John'
console.log(d2); // 'Smith'

Swapping Array Values (Useless)

var a = 1;
var b = 3;

[a, b] = [b, a];
console.log(a); // 3
console.log(b); // 1

Pick values from array (Yuck, they could have made it better by specifying indexes either)

var dudes = [1,2,3,4,5];
var [,,d1, ,d2] = dudes;
console.log(d1); // 3
console.log(d2); // 5

When destructuring an array, you can unpack and assign the remaining part of it to a variable using the rest pattern (In short, pick value and assign rest):

var [a, ...b] = [1, 2, 3];
console.log(a); // 1
console.log(b); // [2, 3]

var [a, b, ...c] = [1, 2, 3];
console.log(a); // 1
console.log(b); // 2
console.log(c); // [3]

Unpacking values from a regular expression match,

function parseProtocol(url) { 
  var parsedURL = /^(\w+)\:\/\/([^\/]+)\/(.*)$/.exec(url);
  if (!parsedURL) {
    return false;
  }
  console.log(parsedURL); // ["https://developer.mozilla.org/en-US/Web/JavaScript", "https", "developer.mozilla.org", "en-US/Web/JavaScript"]

  var [, protocol, fullhost, fullpath] = parsedURL;
  return protocol;
}

console.log(parseProtocol('https://developer.mozilla.org/en-US/Web/JavaScript')); // "https"

Spread Operator (Object)

var o = {x:1};
var p = {y:2, ...o};	// Output: {x:1, y:2}
var q = {o, ...y:2}	// Output: {o: {x:1}, y:2}

Block-Scoped Functions

{
    function foo () { return 1 }
    console.log("foo() === 1: ", foo() === 1)
    {
        function foo () { return 2 }
        console.log("foo() === 2: ", foo() === 2);
    }
    console.log("foo() === 1: ", foo() === 1);
}

Output:

foo() === 1:  true
foo() === 2:  true
foo() === 1:  true

Arrow Functions

  1. In arrow functions you cannot bind this. By Default it points to itself and this cannot be reassigned with call nor apply.
  2. Arrow functions does not have prototype property.
function fn1() {}
const fn2 = () => {}

console.log(fn1.prototype); // {fn1()}
console.log(fn2.prototype); // undefined
  1. You cannot call new on Arrow function to create an object.
const UserDetails = (name) => {
  this.name = name;
}

const user1 = new UserDetails(); // Uncaught TypeError: UserDetails is not a constructor

Variadic Functions (Varargs)

function dude(x, y, ...z) {
	console.log(x, y, z);
}
dude(1,2,3,4,5)

Output:

1, 2, [3,4,5]

New Type of String parameter method call

function getName(str) {
	console.log(str);
}

getName`Deepen`

However, its value is pretty weird, ["Deepen", raw: ["Deepen", ......]]

But this doesnt work

var first = 'Deepen';

getName`${first}`

This is only acceptable for one string value

In short: waste of time, effort of developing this. Dont know who in the world would use this?

Javascript: Understand the Weird Parts

Objects and Functions

Namespaces

A container for variables and functions.

Functions are objects

function greet() {
  console.log('Hello');
}

greet.language='english';
console.log('Greet: ', greet);

First Class Functions

Functions which can be passed around to a variable and created on the fly.

console.log(function() {return "dude";});
function logit(a) {
  return a;
}

console.log(logit(function(){return "dude"}));

this

var o = {
    a: () => {
        console.log(this);

        var some = () => {
            console.log("some: ", this);
        }

        var someone = function() {
            console.log("someone: ", this);
        }

        function sometwo() {
            console.log("sometwo: ", this);
        }
        some();someone();sometwo();

        return () => {console.log("return: ", this);};
    },
    b: function() {
        console.log(this);
    }
}

var

Consider this code.

function dude() {
    var x =1;
    console.log(dude);
}
dude();

Closure

function some(name) {
  return () => {console.log(name);}
}

var someOne = some('Deepen');
someOne(); // Output: Deepen

Here Deepen is printed as outer context is destroyed when someOne() is ran.

Its not only for parameterized variables but also for local variables created inside a function.

function what() {
    var x = 'What Function';

    return () => {console.log(x)};
}

var whatever = what();
whatever(); // Output: What Function

Lets consider another example:

function buildFunctions() {
    var arr = [];

    for(var i=0;i<3;i++) {
        arr.push(
            function() {
                console.log(i);
            }
        );
    }

    return arr;
}

var fs = buildFunctions();

fs[0]();
fs[1]();
fs[2]();

/* Output:
3
3
3
*/

To make it 1,2,3 by creating another execution context inside that function.

function buildFunctions() {
    let arr = [];

    for(var i=0;i<3;i++) {
        arr.push(
            (function(j) {
                return function() {
                    console.log(j);
                }
            })(i)
        );
    }

    return arr;
}

var fs = buildFunctions();

fs[0]();
fs[1]();
fs[2]();

You can also it just with let. It will create 3 different references in closure.

function buildFunctions() {
    var arr = [];

    for(let i=0;i<3;i++) {
        arr.push(
            function() {
                console.log(i);
            }
        );
    }

    return arr;
}

var fs = buildFunctions();

fs[0]();
fs[1]();
fs[2]();

/* Output:
1
2
3
*/

Inheritance, proto and Prototype

Every Object has a property called __proto__ which makes inheritance possible in javascript. Consider following example:

var person = {
    firstname: 'Default',
    lastname: 'Default',
    getFullName: function() {
        return this.firstname + ' ' + this.lastname;
    }
}

var john = {
    firstname: 'John', lastname: 'Doe'
}

// Link to a parent
john.__proto__ = person;

console.log(john.__proto__.firstname) // Default
console.log(john.getFullName()) // John Doe

var jane = {
  firstname: 'Jane'
};

jane.__proto__ = person;

console.log(jane.__proto__.firstname) // Default
console.log(jane.getFullName()) // Jane Default

You should access __proto__ directly, rather use this encapsulated way:

Object.getPrototypeOf(john);
Object.getPrototypeOf(jane);

It will return the object which __proto__ is referring to.

Prototype

On the other hand, prototype is a property on function object. Consider, prototype as the blueprint or class of the object, for example.

function Dog() {}
var dog1 = new Dog();
console.log(dog1.prototype); // {Dog()} <-- this points to blueprint or prototype(english) of the object.

for in loop with Prototype

var Person = {
  firstname: 'Default',
  lastname: 'Default',
  getFullName() {
    return this.firstname+' '+this.lastname
  }
};

var fullname = {
    firstname: 'Deepen',
    middlename: 'Naresh',
    lastname: 'Dhamecha'
}

fullname.__proto__ = Person;

for(var key in fullname) {
    console.log("Key: ", key);
    console.log("Value: ", fullname[key]);
}

It will also print getFullName(). As it is attached to its prototype. To consider only its own properties.

for(var key in fullname) {
    if(fullname.hasOwnProperty(key)) {
      console.log("Key: ", key);
      console.log("Value: ", fullname[key]);
    }
}

Object and new

function Person() {
  this.firstname = 'Deepen';
  this.lastname = 'Dhamecha';
}

If you do this, then it will assign properties and methods on global/window and p1 will be undefined since its just a normal function without returning anything.

var p1 = Person();

But with new keyword,

var p2 = new Person(); // Output: Person {firstname: 'Deepen', lastname: 'Dhamecha'}

This will create a new empty object and assign those properties and methods to it.

If you want to return new object altogether then return from function.

function Person2() {
  this.firstname = 'Deepen';
  this.lastname = 'Dhamecha';

  return {greetings: 'Hello';}
}

var p3 = new Person2();
console.log(p3);

So you can make it like this,

function Person(firstname, lastname) {
  this.firstname = firstname;
  this.lastname = lastname;
}

var john = new Person('John', 'Doe');
console.log(john);

var jane = new Person('Jane', 'Doe');
console.log(jane);

Prototype

When you do new Person(), it creates a function object.

Consider this example,

function Dog() {}

Dog.prototype.breed = 'BullDog';

var dog1 = new Dog();

console.log(dog1.prototype); // undefined

console.log(Dog.prototype); // {breed: 'BullDog', constructor: f}

prototype property is bound to functions and not its object. prototype is used when creating objects. Above showcases on Dog function object but what about object.

Consider this,

console.log(dog1); // Dog {}
console.log(dog1.__proto__); // {breed: 'BullDog', constructor: f}
console.log(dog1.__proto__.__proto__); // {constructor: f, class: Object}
console.log(dog1.__proto__.__proto__.__proto__); // null
console.log(dog1.hasOwnProperty('breed')); // false

So, if you check dog1 object, then breed is not on the object itself but rather on its parent object. So, what prototype does is, when new is invoked on a function, it checks for any prototype assigned. If assigned, then it creates an object of type Dog, assigns prototype attributes to it and links it to __proto__ of the object.

Module imports in NodeJS

You can write

import { dude } from 'filename';

But for this to work, you need to specify one of the 3 things:

  1. File extension as .mjs.
  2. "type":"module" in package.json at the root.
  3. node --input-type=module

Differences between ES modules and CommonJS

No require, exports, or module.exports In most cases, the ES module import can be used to load CommonJS modules.

If needed, a require function can be constructed within an ES module using module.createRequire().

No __filename or __dirname These CommonJS variables are not available in ES modules.

__filename and __dirname use cases can be replicated via import.meta.url.

No Addon Loading Addons are not currently supported with ES module imports.

They can instead be loaded with module.createRequire() or process.dlopen.

No require.resolve Relative resolution can be handled via new URL('./local', import.meta.url).

For a complete require.resolve replacement, there is a flagged experimental import.meta.resolve API.

Alternatively module.createRequire() can be used.

No NODE_PATH NODE_PATH is not part of resolving import specifiers. Please use symlinks if this behavior is desired.

No require.extensions require.extensions is not used by import. The expectation is that loader hooks can provide this workflow in the future.

No require.cache require.cache is not used by import as the ES module loader has its own separate cache.

Map, Set, WeakSet and WeakMap

Set Unique values

var arr = [1,2,3,4];
let mySet = new Set(arr);
console.log(mySet);
for(let s of mySet) {
  console.log(s);
}

Map Key => Value pair

let myMap = new Map([['a1', 'Deepen'], ['a2','Dhamecha']]);

for(let [key, value] of myMap) {
    console.log(`key: ${key}, value: ${value}`);
}

WeakSet and WeakMap are same except that it cannot be iterated.

Event Bubbling and Event Capturing

Event bubbling is event propogating from child to parent.

<!DOCTYPE html>
<html lang="en">
    <head>

      </head>
      <body>
        <div style="padding: 10px;background-color:red;">
          <button>Click me</button>
        </div>

        <script>
          var div = document.querySelector('div');
          var btn = document.querySelector('button');
      
          div.addEventListener("click", function() {
            console.log('div');
          });
      
          btn.addEventListener("click", function() {
            console.log('button');
          });
        </script>
      </body>
</html>
Output:
button
div

Event Capturing is very rare where event is propagating from parent to child.

<!DOCTYPE html>
<html lang="en">
    <head>

      </head>
      <body>
        <div style="padding: 10px;background-color:red;">
          <button>Click me</button>
        </div>

        <script>
          var div = document.querySelector('div');
          var btn = document.querySelector('button');
      
          div.addEventListener("click", function() {
            console.log('div');
          }, true);
      
          btn.addEventListener("click", function() {
            console.log('button');
          }, true);
        </script>
      </body>
</html>

Set true after listener, which reverses event bubbling.

stopPropagation, stopImmediatePropagation and preventDefault

When you modify the above code

btn.addEventListener("click", function(event) {
  console.log('button');
  event.stopPropagation();
});

It prints:

Output:
button

stopPropagation() stops the propagation to its parent. Remember, parent and above and not same sibling or same element.

btn.addEventListener("click", function(event) {
  console.log('button');
  event.stopPropagation();
});

btn.addEventListener("click", function(event) {
  console.log('button 2');
});

Here, button and button2 will be printed.

Functions

Function has a length property which has value of number of parameters.

You cannot this attached with bind to an arrow function.

Currying

This is also known as partial application feature.

let sum = (x,y) => x+y;

let succ = sum.bind(null, 1);

console.log(succ(2)); // Output: 3;
function f(y,z) { return this.x + y + z;}
let g = f.bind({x:1}, 2);

console.log(g(3)); // Output: 6

Function() Constructor

Because functions are objects, there is Function() constructor that can be used to create new functions:

const f = new Function("x", "y", "return x*y");

This line of code creates a new function that is more or less equivalent to a function defined with familiar syntax:

const f = function(x,y) {return x*y};

There are a few points that are important to understand about the Function() constructor:

  1. The Function() constructor allows JavaScript functions to be dynamically created and compiled at runtime.
  2. The Function() constructor parses the function body and creates a new function object each time it is called. If the call to the constructor appears within a loop or within a frequently called function, this process can be inefficient. By contrast, nested functions and function expressions that appear within loops are not recompiled each time they are encountered.
  3. A last, very important point about the Function() constructor is that the functions it creates do not use lexical scoping; instead, they are always compiled as if they were top level functions, as the following code demonstrates:
let scope = "global";
function constructFunction() {
  let scope = "local";
  return new Function("return scope"); // Doesn't capture local scope!
}
// This line returns "global" because the function returned by the
// Function() constructor does not use
// the local scope.
constructFunction()() // => "global"

The Function() constructor is best thought of as a globally scoped version of eval() that defines new variables and functions in its own private scope.

Higher-order functions

A higher-order function is a function that operates on functions, taking one or more functions as arguments and returning a function. Check below,

function not(f) {
  return function(...args) {
    const result = f.apply(this, args);
    return !result;
  }
}

const even = x => x % 2 === 0;

const odd = not(even);

[1,1,3,5,5].every(odd);

This not() function is a higher-order function because it takes a function argument and returns a new function.

Unique elements from Array

let a = ["1", "1", "2", "3", "3", "1"];
let a = ["1", "1", "2", "3", "3", "1"];
let unique = a.filter((item, i, ar) => ar.indexOf(item) === i);
console.log(unique);

In Operator

Consider this object.

const pet = {name: "Kitty", age: 20};
const dog = {name: "Babubhai"};
dog.__proto__ = pet;

console.log(dog.hasOwnProperty('name')); // true
console.log(dog.hasOwnProperty('age')); // false

// But with in operator

console.log('name' in dog); // true
console.log('age' in dog); // true

It checks in parent object as well.

Javascript Classes

If two objects inherit from the same prototype, this typically (but not necessarily) means that they were created and initialized by the same constructor function or factory function.

JavaScript has always allowed the definition of classes. ES6 introduced a brand-new syntax (including a class keyword) that makes it even easier to create classes.

New Javascript classes work in the same way that old-style classes.

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