Javascript Notes
Javascript refresher
let name = "Chandan In JS";
console.log(name);
let firstName = "Chandan";
let lastName = "Jhunjhunwal";
const interestRate = 0.1;
// interestRate = 1;
console.log("Interest rate: ", interestRate)
// Primitive Type Variables:
// String
// Number
// Boolean
// undefined
// null
let str = "Hi"; // String literal
let age = 37; // Number literal
let isApproved = false; // Boolean Literal
let undefVariable = undefined;
let nullVariable = null;
console.log("typeof str: ", typeof str)
str = 10;
console.log("typeof str: ", typeof str)
console.log("typeof isApproved: ", typeof isApproved)
console.log("typeof isApproved: ", typeof isApproved)
console.log("typeof undefVariable: ", typeof undefVariable)
console.log("typeof nullVariable: ", typeof nullVariable)
// Reference types
// Object
// Array
// Functions
// Object
let person = {
firstName: "Chandan",
lastName: "Jhunjhunwal",
age: 37
};
for (let key in person) {
console.log("Key:", key)
console.log("Value", person[key])
}
console.log(person);
console.log(person.firstName);
console.log(person['lastName']);
let selection = "age";
console.log(person[selection]);
console.log("// Array")
let selectedColors = ['red', 'blue', 1, null, false]; // Array Literals
console.log(selectedColors);
selectedColors[5] = 'green';
console.log(selectedColors);
console.log("typeof Array selectedColors", typeof selectedColors)
console.log("Array selectedColors length: ", selectedColors.length)
for(let index in selectedColors) {
console.log("Element at index", index, selectedColors[index])
}
for(let color of selectedColors) {
console.log("Color is", color)
}
selectedColors.forEach(color => console.log(color))
selectedColors.forEach((color, index) => console.log(color, index))
// Functions
function greet(firstName, lastName){
console.log("Hello", firstName, lastName);
}
greet("Chandan", "Jhunjhunwal");
greet("Darsh", "Jhunjhunwal")
greet("Mary")
function square(number){
return number * number;
}
let number = square(2);
console.log(number);
// Strict Equality (Same type and same value)
console.log("1 === 1", 1 === 1);
console.log("'1' === 1", '1' === 1);
// Loose equality - Same value
console.log("1 == 1", 1 == 1);
console.log("'1' == 1", '1' == 1);
console.log("true == 1", true == 1);
// Falsy (false)
// undefined
// null
// 0
// false
// ''
// NaN
// Anything, which is not Falsy -> Truthy
let userColor = undefined;
let defaultColor = "Blue";
let currentColor = userColor || defaultColor;
console.log(currentColor)
// 1 = 00000001
// 2 = 00000010
// 1 | 2 = 00000011
// 1 & 2 = 00000000
console.log(1 | 2);
console.log(1 & 2);
// Read, Write, Execute
// Read permission: 00000100
// Write permission: 00000010
// Execute Permission: 00000001
let readPermission = 4;
let writePermission = 2;
let executePermission = 1;
let myPermission = 0;
// Assign read and write permission
myPermission = myPermission | readPermission | writePermission
console.log(myPermission)
// Check for permission
let doIHaveReadPermission = (myPermission & readPermission) ? 'Yes' : 'No'
console.log(doIHaveReadPermission)
for(let i = 1; i <= 5; i++ ){
console.log("Loop index", i)
}
let whileIndex = 5;
while(whileIndex > 0) {
if (whileIndex % 2 == 0) console.log("while even index", whileIndex);
whileIndex--;
}
// Function for max of an array
function maxOfArray(array){
let maxNum = array[0];
for(let num of array) {
maxNum = maxNum > num ? maxNum : num
}
return maxNum
}
console.log(maxOfArray([1,1000, 4,100,4,5]))
function isLandscape(width, height) {
return width > height
}
function fizzBuzz(n){
if (typeof n !== 'number'){
console.log(NaN)
}
for(let i = 1; i <= n; i++) {
let div_by_2 = (i % 2 === 0);
let div_by_3 = (i % 3 === 0);
if (div_by_2 && div_by_3){
console.log("FizzBuzz")
} else if (div_by_2){
console.log("Fizz")
} else if (div_by_3){
console.log("Buzz")
} else {
console.log(i)
}
}
}
fizzBuzz(1)
fizzBuzz(null)
// Speed Limit = 70
// Anything below 75 = OK
// For every extra 5 speed = 1 points
// If the speed exceeds 120 = license suspended
function speedLimit(speed) {
const limit = 70;
if (speed < (limit+5)) {
console.log('OK')
return
}
points = Math.floor((speed - limit)/5)
if (points < 12) {
console.log("Points:", points)
} else {
console.log("License suspended!")
}
}
speedLimit(70);
speedLimit(74);
speedLimit(75);
speedLimit(110);
speedLimit(120);
speedLimit(170);
function printTruthy(array) {
for(let elem of array) {
if (elem) {
console.log("Truthy:", elem)
} else {
console.log("Falsy", elem)
}
}
}
printTruthy([1, '', null, "HI", undefined, 10.10, NaN])
function showStringProperties(obj){
for(let key in obj) {
if (typeof obj[key] === 'string') {
console.log(key, ":", obj[key])
}
}
};
const movie = {
title: "The Pursuit of Happiness!",
year: 2006,
Director: "Gabriele Muccino",
actor: "Will Smith",
duration: 117
};
showStringProperties(movie)
function getSumOfMultiplesThreeFive(limit){
let sum = 0;
for(let i = 1; i <= limit; i++) {
if (i%3 === 0 || i%5 === 0){
// console.log(i)
// console.log(sum)
sum += i
// console.log(sum)
}
}
console.log(sum)
};
getSumOfMultiplesThreeFive(10)
function showStars(n){
let str = ''
for (let i = 1; i <= n; i++){
str += '*'
console.log(str)
}
}
showStars(10)
// Object
const circle = {
radius: 10,
location: {
x: 1,
y: 2
},
isVisible: true,
draw: function (){
console.log('draw')
}
}
circle.draw();
// Factory functions
// Camel notation
function createCircle(radius, location, isVisible){
return {
radius: radius,
location: location,
isVisible: isVisible,
draw: function (){
console.log('draw')
}
}
}
// A better way to write same thing
function createCircleClean(radius, location, isVisible){
return {
radius, //equivalent to radius: radius
location,
isVisible,
draw(){ // equivalent to draw: function(){ console.log('draw')}
console.log('draw')
}
}
}
const circle1 = createCircleClean(1, {x: 10, y:100}, true)
const circle2 = createCircleClean(100, {x: 1, y:10}, false)
console.log(circle1);
circle1.draw();
console.log(circle1.radius);
console.log(circle1.location);
console.log(circle1.radius);
console.log(circle2);
// Iterating through objects
console.log("// Iterating through objects")
for(let key in circle) {
console.log(key)
}
// for of loop can only be used with the objects having 'iterator' method
for(let key of Object.keys(circle)){
console.log(key)
}
for(let entity of Object.entries(circle)){
console.log(entity)
}
if ('radius' in circle) { console.log("Yes")}
// Cloning object
const anotherCircle = {}
for(let key in circle) {
anotherCircle[key] = circle[key]
}
console.log(anotherCircle)
// another way of cloning
const anotherClone = Object.assign({}, circle)
console.log(anotherClone)
// another way of cloning using spread operator
const yetAnotherClone = { ...circle }
console.log(yetAnotherClone)
// Constructor function
// Pascal notation
function Circle(radius, location, isVisible){
this.radius = radius;
this.location = location;
this.draw = function(){
console.log('draw')
}
}
const circle3 = new Circle(10, {x: 10, y: 10}, true)
console.log(circle3)
circle3.draw()
// NOTE: Factory function and constructor function, both are meant to create objects
// The only difference is convention
// Dynamic property of object
const squareShape = {
side: 10
};
// Following reassignment to new object will not work as squareShape is defined as "const"
// squareShape = {};
console.log(squareShape);
// Properties can be added dynamically
squareShape.area = squareShape.side**2
console.log(squareShape);
// A function can be added dynamically as property
squareShape.draw = function(){
console.log('draw');
}
console.log(squareShape);
squareShape.draw();
// A property can be deleted
delete squareShape.area;
delete squareShape.side;
console.log(squareShape)
// Every object has "constructor" property, which is actually used to create that object
// Javascript internally defines contructor for each object, unless an explicit contructor is defined.
// Example above "Circle" is explicit contructor
//
// circle2.constructor
// ƒ Object() { [native code] }
// circle3.constructor
// ƒ Circle(radius, location, isVisible){
// this.radius = radius;
// this.location = location;
// this.draw = function(){
// console.log('draw')
// }
// }
// In JS, functions are objects
const CustomCircle = new Function('radius', `
this.radius = radius;
this.draw = function(){
console.log('draw')
}
`)
const myCircle = new CustomCircle(1);
const myNewCircle = CustomCircle.call({}, 10); // TODO: Logs undefined
console.log(myCircle)
console.log(myNewCircle)
// Primitives are copied by value
// Objects are copied by reference.
let myNumber = 10;
function incrementNum(myNumber){
myNumber++;
}
incrementNum(myNumber);
console.log(myNumber); // logs 10
let numObject = {value: 10};
function incrementObjNum(numObject){
numObject.value++
}
incrementObjNum(numObject);
console.log(numObject) // logs value: 11
console.log("// String ")
const myStr = 'hi';
console.log(typeof myStr); // 'string'
const anotherStr = new String('hi');
console.log(typeof anotherStr) // 'object'
console.log("// Template Literals")
let mailMsg = "Hi " + firstName + " " + lastName + "\n"
console.log(mailMsg);
// Using template literals
let tMaillMsg =
`Hi ${firstName} ${lastName},
Thank you for subscribing to my newsletter.
Cheers,
Chandan`
console.log(tMaillMsg)
// Address contstructor
class Address {
constructor(street, city, zipcode) {
this.street = street;
this.city = city;
this.zipcode = zipcode;
}
}
// Factory function
function createAddress(street, city, zipcode){
return {
street,
city,
zipcode
}
}
// const yetAnotherCreateAddress = new function ("street", "city", "zipcode", `
// this.street = street;
// this.city = city;
// this.zipcode = zipcode;
// `)
const address = new Address("Handewadi", "Pune", 411028)
const anotherAddress = createAddress("Station Road", "Sakri", 847239)
function showAddress(address){
for(let entry of Object.entries(address)){
console.log(entry)
}
}
showAddress(address)
showAddress(anotherAddress)
function equalAddress(address1, address2) {
if (JSON.stringify(Object.keys(address1)) !== JSON.stringify(Object.keys(address2))){
return false
}
let equal = true
for(let key in address1) { // but address2 can have additional keys or some keys from address1 might have been deleted.
if (address1[key] != address2[key]){
equal = false
break
}
}
return equal
}
console.log(equalAddress(address, anotherAddress))
console.log(equalAddress(anotherAddress, anotherAddress))
function sameAddress(address1, address2) {
return (address1 === address2)
}
console.log(sameAddress(address, anotherAddress))
console.log(sameAddress(anotherAddress, anotherAddress))
class BlogPost {
constructor(title, body, author, views, comments, isLive) {
this.title = title;
this.body = body;
this.author = author;
this.views = views || 0;
this.comments = comments || [];
this.isLive = isLive || false;
}
}
class Comment{
constructor(author, body) {
this.author = author;
this.body = body
}
}
let newPost = new BlogPost(
"First Post",
"Post body",
"Chandan"
)
let oldPost = new BlogPost(
"First Post",
"Post body",
"Chandan",
100,
[new Comment('chandan', 'Hi')],
true
)
console.log(newPost)
console.log(oldPost)
// Array
// Combine Array
a1 = [1,2,3,4]
a2 = [5,6,78]
const combined = [...a1, ...a2]
const course_list = [
{id: 1, name: "Node.JS"},
{id: 2, name: "Javascript"},
{id: 3, name: "GoLang"},
{id: 4, name: "Ruby"}
]
console.log(course_list)
course_list.sort((c1, c2) => {
const name1 = c1.name.toUpperCase();
const name2 = c2.name.toUpperCase();
if (name1 < name2) return -1
if (name2 > name1) return 1
return 0
})
console.log(course_list) // It'll modify the original object, so any earlier reference to course_list will also see this mutation
const arr = [1,2,3,5]
const allPositive = arr.every(element => element > 0)
console.log(allPositive)
const arr1 = [1,23,-1]
const someNegative = arr1.some(element => element < 0)
console.log(someNegative)
const arr2 = [1,2,-1,4,5]
const filteredArr = arr2.filter(element => element > 0)
console.log(filteredArr)
const items = filteredArr.map(element => "<li>" + element + "</li>")
const html = "<ul>" + items.join('') + "</ul>"
console.log(items)
console.log(html)
console.log(items.map (element => ({value: element})))
// Chainable
const polishedItems = arr2
.filter(ele => ele > 0)
.map(ele => ({value: ele}))
.filter(ele => ele.value > 3)
console.log("polished items:", polishedItems)
const sum = arr2.reduce((accumulator, current_value) => {
return accumulator + current_value
}, 0)
console.log(sum)
console.log("// Array excercise 1")
const numbers = arrayFromRange(-10, 5)
console.log(numbers);
function arrayFromRange(min, max) {
let array = []
for(let i = min; i <= max; i++) {
array.push(i)
}
return array
}
console.log("// Array excercise 2")
console.log(customIncludes(numbers, 5))
function customIncludes(array, searchElem) {
for(i=0; i < array.length; i++){
if (array[i] === searchElem) return true
}
return false
}
console.log("// Array excercise 3")
const arr_ex3 = [1,2,3,4,5,6,7,1,1,1]
console.log(arr_ex3)
console.log(excludes(arr_ex3, [1,2,3,4]))
function excludes(input_array, exclude_array) {
const resulting_array = []
for(let elem of input_array) {
if (exclude_array.indexOf(elem) < 0){
resulting_array.push(elem)
}
}
return resulting_array
}
console.log("// Array excercise 4")
const arr_ex4 = [1,2,3,4]
const output = move(arr_ex4, 1, -1); // Move element at index 1 to index 3
console.log(output)
function move(input, elem_index, offset) { // offset is new index
if(elem_index >= input.length){
console.error("Invalid element index")
return
}
if(elem_index+offset < 0){
console.error("Invalid offset")
return
}
const output = [];
// when offset positive
// all elements before elem_index will remain as it is
// all elements after elem_index + offset will remain same
// all elements between elem_index and elem_index + offset will shift left by 1
// element at elem_index+offset will be input[elem_index]
if (offset >= 0) {
input.forEach((elem, index) => {
if(index < elem_index) {
output.push(elem)
} else if (index > elem_index + offset) {
output.push(elem)
} else if ((index >= elem_index) && (index < elem_index + offset)) {
output.push(input[index+1])
} else if (index === elem_index + offset){
output.push(input[elem_index])
}
})
} else {
// when offset negative
// all elements before elem_index + offset will remain as it is
// all elements after elem_index will remain as it is
// all elements after elem_index + offset and before elem_index will shift right by 1
// element at elem_index+offset will be input[elem_index]
input.forEach((elem, index) => {
if(index < (elem_index+offset)) {
output.push(elem);
} else if (index > elem_index) {
output.push(elem)
} else if ((index > elem_index+offset) && (index <= elem_index)) {
output.push(input[index-1])
} else if (index === elem_index + offset) {
output.push(input[elem_index])
}
})
}
// Another solution
const output_1 = [...input];
const element = output_1.splice(elem_index, 1)[0]
output_1.splice(elem_index+offset, 0, element)
return output
// let output_array = [];
// let new_position = elem_index + offset
// let original_array = [...input]
// // delete the element from array
// shifting_elem = input.splice(elem_index, 1)
// // new_position > elem_index?
// for(let i = 0; i < original_array.length; i++ ){
// // Anything before new_position should remain as it is
// // Everything after new position should be shifted
// if (i == new_position) {
// output_array = output_array.concat(shifting_elem)
// } else if (i < elem_index) {
// output_array.push(original_array[i])
// } else {
// output_array.push(original_array[i+1])
// }
// }
// // push all elements to output until reach at elem_index
// // copy elem_index in temp variable and start pushing next elements upto elem_index + offset - 1
// // push the temp variable at elem_index+offset
// // push remaining elements to output
// let temp;
// input.forEach((elem, index) => {
// if (index < elem_index) {
// output_array.push(elem)
// } else if (index == elem_index) {
// temp = elem;
// } else if (index <= (elem_index+offset-1)) {
// output_array.push(input[index])
// } else if (index === elem_index+offset) {
// output_array.push(temp)
// } else if (index > elem_index+offset){
// output_array.push(elem)
// }
// })
// return output_array
}
console.log("// Count occurence Array ex 5")
const num_ex5 = [1,2,3,4,4,5]
const count_ex5 = countOccurences(num_ex5, 4);
console.log(count_ex5);
console.log(countOccurencesReduce(num_ex5, 4));
function countOccurences(input, searchElement){
let count=0;
for(let num of input){
if (num === searchElement) {
count++;
}
}
return count
}
function countOccurencesReduce(input, searchElement){
return input.reduce((count, elem) => {
const occured = (elem === searchElement) ? 1 : 0;
return count + occured;
}, 0
)
}
console.log("//Get Max of an array ex6")
const num_ex6 = [1,2,3,4,2,100]
const max_ex6 = getMax(num_ex6)
console.log(max_ex6)
function getMax(input){
if (input.length === 0) {
return undefined;
}
return input.reduce((accumulator, elem) => {
return accumulator > elem ? accumulator : elem
}, input[0])
}
console.log("//Movies ex7")
// All movies in 2018 with rating > 4
// Sort them by rating desc
// pick their title
const movies = [
{
title: 'c',
year: 2019,
rating: 4.5
},
{
title: 'd',
year: 2028,
rating: 4
},
{
title: 'e',
year: 2018,
rating: 5
},
{
title: 'b',
year: 2018,
rating: 4
},
{
title: 'a',
year: 2018,
rating: 4.5
}
]
console.log(pickMoviesInYear(movies, 2018, 4));
function pickMoviesInYear(movies, year, rating) {
// Solution 1
// const movies_in_year = []
// for(let movie of movies){
// if(movie.year === year && movie.rating >= rating){
// movies_in_year.push(movie)
// }
// }
// return movies_in_year.sort((m1, m2) => {
// const m1Title = m1.title.toUpperCase();
// const m2Title = m2.title.toUpperCase();
// if (m1Title < m2Title) return -1;
// if (m1Title > m2Title) return 1;
// return 0;
// }).map(movie => movie.title)
// Solution 2:
const titles = movies
.filter(m => m.year === year && m.rating >= rating)
.sort((m1, m2) => m1.rating - m2.rating)
.reverse()
.map(m => m.title)
return titles
}
console.log("// Functions")
// Function declaration
// Can be called before this function declaration
// "Hoisting" = moving the function declaration to the top of file.
function walk(){
console.log('walk')
}
// Anonymous Function expressions
// Can be called only after the below expression, as run is a variable
let run = function(){
console.log('run');
};
let running = run;
run();
running();
// Named Function expressions
let runNamed = function runNamed (){
console.log('run');
};
// "arguments" inside a function
function sumAll(){
let total = 0;
for(let num of arguments) {
total += num
}
return total
}
console.log(sumAll(1,2,3,4,5,6,7))
// Rest operator/parameter
function sumAllRestOperator(...args){
return args.reduce((a,b) => a+b)
}
console.log(sumAllRestOperator(1,2,3,4,5,6,7))
// Rest parameter must be last parameters in a function definition
// i.e. after explicit arguments, rest all are rest parameters, that's why it's called rest operator.
function finalPrice(discount, ...prices){
return prices.reduce((a,b) => a+b)*(1-discount)
}
console.log(finalPrice(0.1, 100,200))
// Default arguments
// IMPORTANT: If a default value is provided for an argument, any argument after that should also have default value
// else the defaulted argument will have to be passed as undefined to pass next argument without default value
function calculateInterest(principle, interest = 3.5, duration = 5){
return principle*(interest/100)*duration
}
console.log(calculateInterest(100))
console.log(calculateInterest(100, 5))
console.log(calculateInterest(100, 5 , 10))
function acheck(p, i = 10, j){
return p*i*j
}
// If we don't want to pass value of i, then pass it as undefined.
acheck(10, undefined, 10)
console.log("//Getter/Setter")
const human = {
firstName: "Chandan",
lastName: "Jhunjhunwal",
get fullName(){
return `${this.firstName} ${this.lastName}`
},
set fullName(value) {
if (typeof value !== 'string'){
throw new Error("Please pass a valid string");
}
const parts = value.split(' ');
if (parts.length !== 2) {
throw new Error("Please enter first and last name");
}
this.firstName = parts[0]
this.lastName = parts[1]
}
}
human.fullName = "Darsh J"
// try {
// human.fullName = null;
// }
// catch (e){
// alert(e);
// }
// try {
// human.fullName = ''
// }
// catch (e){
// alert(e);
// }
// try {
// human.fullName = 'Chandan'
// }
// catch (e){
// alert(e);
// }
console.log(human)
console.log("//var vs let")
// Var defines a variable available within whole function, where as let is block scoped
function varLet(){
for(var i = i; i <=5; i++){
if(true) {
var j = 100;
}
}
console.log(i);
console.log(j)
}
varLet();
// Defines window level variable
var windowLevel = 'red';
// this(->)
// method -> obj
// function -> global ("window" in browser, "global" in node)
const myObj = {
id: 1,
cat(){
console.log(this)
}
}
myObj.cat();
myObj.dog = function(){
console.log(this)
}
myObj.dog();
function playVideo(){
console.log(this)
}
playVideo();
class Video {
constructor(title) {
this.title = title;
console.log(this)
}
}
const v = new Video('video title') // here -> refers to {} as new keyword is used
const video = {
id: 1,
tags: ['drama', 'violence', 'drug'],
showTags(){
const self = this;
this.tags.forEach(function(tag){ // this function is anonymous function, so "this" is "window". Need to pass "this" as last argument
console.log(this.id, tag);
console.log(self.id, tag)
}, this)
}
}
video.showTags();
// Changing this for global function
function playVideoFn(a,b){
console.log(this);
}
// call access first argument for this and other arguments as next arguments
playVideo.call({name: "Chandan"}, 1,2)
// apply access first argument for this and other arguments in an array
playVideo.apply({id: 100}, [100,200])
// bind binds the argument object to returned function permanently
const fn = playVideo.bind({obj_id: 1})
fn()
// bind(ed) function can be called directly
playVideo.bind({x: 100})();
const video1 = {
id: 1,
tags: ['drama', 'violence', 'drug'],
showTags(){
const self = this;
this.tags.forEach(function(tag){ // this function is anonymous function, so "this" is "window". Need to pass "this" as last argument
console.log(this.id, tag);
}.bind(this))
}
}
video1.showTags();
// ES6 using arrow function - arrow function keeps the context of "this"
const video2 = {
id: 1,
tags: ['drama', 'violence', 'drug'],
showTags(){
this.tags.forEach(tag => console.log(this.id, tag))
}
}
video2.showTags();
// functions excercise 1
const sumAllVersatile = function(...args){
if(args.length === 1 && Array.isArray(args[0])){
args = [...args[0]] //OR
// args = args[0]
}
return args.reduce((a,n) => a+n)
}
console.log(sumAllVersatile(1,2,3,4));
console.log(sumAllVersatile([1,2,3,4]));
// functions excercise 2
// circle.radius = 2 - Read and Write
// circle.area - Read only
const circle_ex2 = {
radius: 1,
get area(){
return Math.PI*this.radius*this.radius
}
}
console.log(circle_ex2);
console.log(circle_ex2.radius);
console.log(circle_ex2.area);
circle_ex2.radius = 2;
console.log(circle_ex2);
console.log(circle_ex2.radius);
console.log(circle_ex2.area);
// functions excercise 3
try {
const numbers_ex3 = [1,2,3,4,5, 1]
// const count_ex3 = countOccurencesEx3(numbers_ex3, 1);
const count_ex3 = countOccurencesEx3(true, 1);
console.log(count_ex3);
}
catch (e){
console.log(e)
}
function countOccurencesEx3(array, searchElem){
if(!Array.isArray(array)){
throw new Error("Please pass array as first argument")
}
return array.reduce((count, elem) => {
const occured = (elem == searchElem) ? 1 : 0;
return count += occured;
}, 0);
}
This is a sapling 🌱 in my digital garden 🏡.
Notes mentioning this note
There are no notes linking to this note.