« Javascript interview questions
What are the different data types present in javascript?
To know the type of a JavaScript variable, we can use the typeof operator.
Primitive types
String
- It represents a series of characters and is written with quotes. A string can be represented using a single or a double quote.
1var str = 'Vivek Singh Bisht'; //using double quotes2var str2 = 'John Doe'; //using single quotes
Number
- It represents a number and can be written with or without decimals.
1var x = 3; //without decimal2var y = 3.6; //with decimal
BigInt
- This data type is used to store numbers which are above the limitation of the Number data type. It can store large integers and is represented by adding “n” to an integer literal.
1var bigInteger = 234567890123456789012345678901234567890;
Boolean
- It represents a logical entity and can have only two values : true or false. Booleans are generally used for conditional testing.
1var a = 2;2var b = 3;3var c = 2;4a == b;5a == c;
Undefined
- When a variable is declared but not assigned, it has the value of undefined and it’s type is also undefined.
1var x; // value of x is undefined2var y = undefined; // we can also set the value of a variable as undefined
Null
- It represents a non-existent or a invalid value.
1var z = null;
Symbol
- It is a new data type introduced in the ES6 version of javascript. It is used to store an anonymous and unique value.
1var symbol1 = Symbol('symbol');2typeof of primitive types :3typeof "John Doe" // Returns "string"4typeof 3.14 // Returns "number"5typeof true // Returns "boolean"6typeof 234567890123456789012345678901234567890n // Returns bigint7typeof undefined // Returns "undefined"8typeof null // Returns "object" (kind of a bug in JavaScript)9typeof Symbol('symbol') // Returns Symbol
Non-primitive types
Primitive data types can store only a single value. To store multiple and complex values, non-primitive data types are used.
Object
- Used to store collection of data.
1var obj1 = {2 x: 43,3 y: 'Hello world!',4 z: function () {5 return this.x;6 },7};
// Collection of data as an ordered list
1var array1 = [5, 'Hello', true, 4.1];
Note- It is important to remember that any data type that is not a primitive data type, is of Object type in javascript.
Explain Hoisting in javascript
Hoisting is the default behaviour of javascript where all the variable and function declarations are moved on top.
This means that irrespective of where the variables and functions are declared, they are moved on top of the scope. The scope can be both local and global.
Example 1:
hoistedVariable = 3; console.log(hoistedVariable); // outputs 3 even when the variable is declared after it is initialized var hoistedVariable; Example 2:
hoistedFunction(); // Outputs " Hello world! " even when the function is declared after calling
function hoistedFunction(){ console.log(" Hello world! "); } Example 3:
// Hoisting takes place in the local scope as well function doSomething(){ x = 33; console.log(x); var x; } doSomething(); // Outputs 33 since the local variable “x” is hoisted inside the local scope
Note - Variable initializations are not hoisted, only variable declarations are hoisted: var x; console.log(x); // Outputs "undefined" since the initialization of "x" is not hoisted x = 23; Note - To avoid hoisting, you can run javascript in strict mode by using “use strict” on top of the code: "use strict"; x = 23; // Gives an error since 'x' is not declared var x;
Difference between “ == “ and “ === “ operators.
Both are comparison operators. The difference between both the operators is that "==" is used to compare values whereas, "===" is used to compare both values and types.
1var x = 2;2var y = '2';3x == y; // Returns true since the value of both x and y is the same4x === y; // Returns false since the typeof x is "number" and typeof y is "string"
Difference between var, let and const keywords in JavaScript
Objects in javascript
Now each value of each keys we have here can be any type in JavaScript, it can be a number, a string, a boolean, null, undefined, it can even be another object, or an array, or a function.
Function vs Methods
If a function is part of an object, in object oriented programming terms, we refer to that function as a method.
Factory functions
1function createCircle(radius) {2 // return {3 // radius: radius,4 // draw: function(){5 // console.log('circle draw method called fronm factory function');6 // }7 // };8 return {9 radius,10 draw() {11 console.log('circle draw method called from factory function');12 },13 };14}1516const circle1 = createCircle(5);17circle1.draw();
Constructor function
When we use the new operator, 3 things happen:
- this operator first creates an empty object
- then it will set this to point to this object
- and finally it will return that object from this function.
1function Circle(radius) {2 this.radius = radius;3 this.draw = function () {4 console.log('draw from Constructor function');5 };6}78const circle2 = new Circle(7);9circle2.draw();
Objects in JavaScript
Objects in JavaScript are dynamic which means once you create them you can always add new properties or methods, or remove existing ones.
1const myCircle = {2 radius: 5,3};45console.log(myCircle);6myCircle.color = 'red';7console.log(myCircle);8myCircle.draw = function () {};9console.log(myCircle);10delete myCircle.color;11console.log(myCircle);12delete myCircle.radius;13console.log(myCircle);
Every object in javascript has a property called constructor
And that references the function that was used to construct or create that object.
1function createCircle(radius){2 // return {3 // radius: radius,4 // draw: function(){5 // console.log('circle draw method called fronm factory function');6 // }7 // };8 return {9 radius,10 draw(){11 console.log('circle draw method called from factory function');12 }13 };14}1516const circle1 = createCircle(5);17circle1.draw();1819circle1.constructor20ƒ Object() { [native code] }2122function Circle(radius){23 this.radius = radius;24 this.draw = function(){25 console.log('draw from Constructor function');26 }27}2829const circle2 = new Circle(7);30circle2.draw();3132circle2.constructor33ƒ Circle(radius){34 this.radius = radius;35 this.draw = function(){36 console.log('draw from Constructor function');37 }38}
This is a built it constructor function in javascript. When we create an object using object literal syntax, internally the JavaScript engine uses this constructor function.
1ƒ Object() { [native code] }
In JavaScript we have a few other built in constructors,
So, single quotes or double code, or back tick. Using these literals is cleaner and simpler than using the constructor.
1const an =""2an.constructor3ƒ String() { [native code] }
1new String();2new Boolean();3new Number();
Functions are objects
1Circle.constructor2ƒ Function() { [native code] }
When we declare a function using this syntax, internally, JavaScript engine will use this function constructor to create this object.
Internally, JavaScript engine will use this Function
constructor to create this object.
In Javascript we have 2 categories of types
Value types:
- Number
- String
- Boolean
- Symbol
- undefined
- null
Value types:
- Objects
- Functions
- Arrays
Objects are not iterables
for of loop can only be used with iterables
Constructor Object Function
Whenever we create object using object literal syntax internally that is translated to a call to this constructor function.
Internally this
1const x = { value: 1 };
is translated to
1const x = new Object();
Object keys
This method returns string array of keys.
1for (let key of Object.keys(circle)) {2 console.log(key);3}
Object Entries
1for (let key of Object.entries(circle)) {2 console.log(key);3}
Check if a key exists in object
1if ('radius' in circle) console.log('yes');
Cloning Object
Object.assign
1const circle = {2 radius: 1,3 draw: function () {4 console.log('draw');5 },6};78const another1 = Object.assign({}, circle);9const another2 = Object.assign({ color: 'red' }, circle);1011console.log(another1);12console.log(another2);
spread operator
1const circle = {2 radius: 1,3 draw: function () {4 console.log('draw');5 },6};78const another = { ...circle };9console.log(another);
Garbage Collector
A javascript engine has a garbage collector. It finds constants and variables and then de-allocate the memory that was allocated to them. Memory allocation and de-allocation happens automatically behind the scenes and I have no control over that. We can't tell Garbage Collector when to run and de-allocate which objects from the memory.
Math Object
Math.round(1.9)
Math object
1console.log(Math.round(1.9));2console.log(Math.max(1, 2, 6, 0, -2));3console.log(Math.min(1, 2, 6, 0, -2));
String
In javascript we have 2 types of strings. One is primitive string
another is string object
. When we use the dot notation with a string primitive, JavaScript engine internally wraps this with a string object, we don't see that, but we can work with this like a string object.
1const message = 'Anish';2console.log(typeof message);3const another = new String('Dubey');4console.log(typeof another);
1const message = 'This is my first message';2console.log(typeof message);3const another = new String('Dubey');4console.log(typeof another);56console.log(message.length);7console.log(message[0]);8console.log(message[1]);9console.log(message.includes('An'));10console.log(message.includes('an'));11console.log(message.includes('my'));12console.log(message.includes('This'));13console.log(message.includes('this'));14console.log(message.startsWith('This'));15console.log(message.startsWith('me'));16console.log(message.endsWith('message'));17console.log(message.endsWith('me'));18console.log(message.indexOf('me'));19console.log(message.replace('first', 'second'));20console.log(message);21console.log(message.toUpperCase());22console.log(message.toLowerCase());23console.log(message);2425const unTrimmedMessage = ' This is my untrimmed message. ';26console.log(unTrimmedMessage.trim());27console.log(unTrimmedMessage);2829const newLineMessage = 'This is my\n first message';30console.log(newLineMessage);3132const escapeCharMessage = "This is my 'first message";33console.log(escapeCharMessage);3435console.log(message.split(' '));
Template literals
1const name = 'Anish';23const message = `Hi ${name} ${2 + 3}45Thank you for joining my mailing list67Regards8Anish9`;1011console.log(message);
Date
1const now = new Date();2const date1 = new Date('May 11 2018 09:00');3const date2 = new Date(2017, 4, 11, 9);45console.log(now);6console.log(date1);7console.log(date2);89now.setFullYear(2005);10console.log(now);
Object Equality
1let address1 = new Address('a', 'b', 'c');2let address2 = new Address('a', 'b', 'c');3let address3 = address1;45function Address(street, city, zipCode) {6 this.street = street;7 this.city = city;8 this.zipCode = zipCode;9}1011function areEqual(address1, address2) {12 return (13 address1.street === address2.street &&14 address1.city === address2.city &&15 address1.zipCode === address2.zipCode16 );17}1819function areSame(address1, address2) {20 return address1 === address2;21}2223console.log(areEqual(address1, address2));24console.log(areSame(address1, address2));25console.log(areSame(address1, address3));
Adding elements in Array
1const numbers = [3, 4, 1, 3];23numbers.push(5, 6);4numbers.unshift(1, 2);5numbers.splice(2, 0, 'a', 'b');6console.log(numbers);78console.log(numbers.indexOf(1));9console.log(numbers.indexOf(4));10console.log(numbers.indexOf(9));1112console.log(numbers.lastIndexOf(1));1314console.log(numbers.includes(5));15console.log(numbers.includes(9));1617console.log(numbers.indexOf(1));18console.log(numbers.indexOf(1, 3));
All these methods have second parameter that is optional that is starting index
.
Array find method
1const courses = [2 { id: 1, name: 'a' },3 { id: 2, name: 'b' },4];56const course = courses.find(function (course) {7 return course.name === 'a';8});910console.log(course);1112const course1 = courses.find(function (course) {13 return course.name === 'xyz';14});1516console.log(course1);1718const courseIndex = courses.findIndex(function (course) {19 return course.name === 'xyz';20});2122console.log(courseIndex);2324const courseIndex1 = courses.findIndex(function (course) {25 return course.name === 'b';26});2728console.log(courseIndex1);
If not found then undefined will be returned and if found that particular element of the array is returned.
Shorter way using arrow functions.
1const courses = [2 { id: 1, name: 'a' },3 { id: 2, name: 'b' },4];56const course = courses.find((course) => course.name === 'a');78console.log(course);
Removing elements from Array
1const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9];23const last = numbers.pop();4console.log(last);5console.log(numbers);67const first = numbers.shift();8console.log(first);9console.log(numbers);1011numbers.splice(2, 3);12console.log(numbers);
Emptying the array
1let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9];2let another = numbers;34// This won't work if we have multiple references to the original array5numbers = [];67console.log(numbers);8console.log(another);
1let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9];2let another = numbers;34numbers.length = 0;56console.log(numbers);7console.log(another);
1let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9];2let another = numbers;34numbers.splice(0, numbers.length);56console.log(numbers);7console.log(another);
1let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9];2let another = numbers;34//This is not ideal where we have a million elements Because then pop will be called a million times5while (numbers.length > 0) {6 numbers.pop();7}89console.log(numbers);10console.log(another);
Combining and slicing arrays
1const first = [1, 2, 3, 4];2const second = [7, 8, 9, 10];34const combined = first.concat(second);56console.log({ combined });7console.log({ first });8console.log({ second });910const slice = combined.slice(2, 5);1112console.log({ slice });13console.log({ combined });1415const slice1 = combined.slice(2);16console.log({ slice1 });1718// this will copy the entire array19const combined2 = combined.slice();20console.log({ combined2 });
In both these methods if we are dealing with primitive values then these primitive values will be copied to the new array. But if you have objects inside array then those are not copied their references are copied that means input in both the arrays will point to the same object.
1const first = [1, 2, 3, { id: 5 }];2const second = [7, 8, 9, 10];34const combined = first.concat(second);56first[3].id = 115;78console.log({ combined });9console.log({ first });10console.log({ second });
Shorter using spread operator
1const first = [1, 2, 3, { id: 5 }];2const second = [7, 8, 9, 10];34const combined = [...first, ...second];5const combined1 = [...first, 'a', ...second, 'b'];67console.log({ combined });8console.log({ combined1 });9console.log({ first });10console.log({ second });
Iterating through array
1const numbers = [1, 2, 3, { id: 5 }];23for (let num of numbers) {4 console.log(num);5}67numbers.forEach(function (num) {8 console.log(num);9});1011numbers.forEach((num) => console.log(num));12numbers.forEach((num, index) => console.log(index, num));
Joining Arrays
1const numbers = [1, 2, 3, 4];2const joined = numbers.join(',');3console.log(joined);45const message = 'This is my message';6const parts = message.split(' ');7console.log(parts);89console.log(parts.join('-'));
Sorting Arrays
1const numbers = [2, 3, 1];2numbers.sort();3console.log(numbers);45numbers.reverse();6console.log(numbers);
sorting objects
1const courses = [2 { id: 1, name: 'Nodejs' },3 { id: 2, name: 'javascript' },4];5console.log(courses);67courses.sort(function (a, b) {8 const nameA = a.name.toLowerCase();9 const nameB = b.name.toLowerCase();1011 if (nameA < nameB) return -1;12 if (nameA > nameB) return 1;1314 return 0;15});1617console.log(courses);
Testing elements of array
every method
& some method
1const numbers = [1, -1, 2, 3];23const allPositive = numbers.every(function (value) {4 return value >= 0;5});67console.log(allPositive);89const atLeastOnePositive = numbers.some(function (value) {10 return value >= 0;11});1213console.log(atLeastOnePositive);
As soon as every
finds an element that doesn't match this criteria, it's going to stop searching.
As soon as some
finds an element that matches this criteria, it's going to return true.
Filtering Arrays
1const numbers = [1, -1, 2, 3];23const filtered = numbers.filter(function (value) {4 return value >= 0;5});67console.log(filtered);
shorter using arrow functions.
1const numbers = [1, -1, 2, 3];23const filtered = numbers.filter((value) => value >= 0);45console.log(filtered);
Mapping an array
these don't modify original array. They return new array;
1const numbers = [1, -1, 2, 3];2const items = numbers.map((n) => '<li>' + n + `</li>`);3const html = '<ul>' + items.join('') + '</ul>';4console.log(html);56const items1 = numbers.map((n) => {7 const obj = { value: n };8 return obj;9});1011console.log(items1);
Chaining methods
1const numbers = [1, -1, 2, 3];2const items = numbers3 .filter((n) => n >= 0)4 .map((n) => ({ value: n }))5 .filter((obj) => obj.value > 1)6 .map((obj) => obj.value);78console.log(items);
Reducing an array
1let numbers = [1, -1, 2, 3];23let sum = 0;45for (let number of numbers) {6 sum = sum + number;7}89console.log(sum);1011numbers = [1, 2, 3];1213const ans = numbers.reduce((accumulator, currentValue) => {14 return accumulator + currentValue;15}, 0);1617console.log(ans);
This callback function is executed multiple times, each time this currentValue will be set to one element in this array. So in each call, we want to get this currentValue and add it to accumulator.
Now we can make this code even shorter. We can exclude the initialization of the accumulator, and with this, accumulator will be set to the first element and currentValue to be the second element.
1let numbers = [1, 2, 3];23const ans = numbers.reduce((accumulator, currentValue) => {4 return accumulator + currentValue;5});67console.log(ans);
Functions
We can use the function declaration syntax or function expression which basically involves declaring a variable or a constant.
1//Function declaration2function walk() {3 console.log('walk');4}56//Anonymous function expression7const run = function () {8 console.log('walk');9};1011//Named function expression12const run1 = function walk1() {13 console.log('walk');14};1516let move = run;1718run();19walk();20run1();21move();
Hoisting in Javascript
We can call a function that is defined using the function declaration syntax before it's definition. The reason for this is because when our JavaScript engine executes this code, it moves all the function declarations to the top.
Hoisting is the process of moving function declarations to the top of the file. And this is done automatically by the JavaScript engine that is executing this code.
1walk();2function walk() {3 console.log('walk');4}56// run(); // this will give error Cannot access 'run' before initialization7const run = function () {8 console.log('walk');9};
Javascript is a dynamic language
JavaScript is a dynamic language, so we can declare a variable, set it to a number and then change its type and set it to a string and that perfectly fine from the perspective of a JavaScript engine.
1let x = 1;2console.log(x);34x = 'a';5console.log(x);
Arguments
But in JavaScript, it doesn't matter that if a function has 2 parameters, we can pass only 1 argument. We can even pass no arguments.
1function sum(a, b) {2 return a + b;3}45console.log(sum(1, 2));6console.log(sum(1)); //a=1 b=undefined so answer is NaN7console.log(sum()); //a=undefined b=undefined so answer is NaN
We can even pass additional arguments.
Every function in JavaScript has a special object called arguments
. arguments
has a length
property that returns the number of arguments
that are passed. We have this other property, callee
which returns the currently executed function, so you see we have a reference to our sum function.
We can use the for of loop
, on arrays, but technically this loop can be used on any object that has an iterator. So the plain objects that we create with the object literal syntax, they don't have an iterator, but this particular object you can see, here we have symbol.iterator
.
1function sum(a, b) {2 console.log(arguments);3 return a + b;4}56console.log(sum(1, 2, 3, 4, 5));78function sum1(a, b) {9 let total = 0;10 for (let value of arguments) {11 total = total + value;12 }13 return total;14}1516console.log(sum1(1, 2, 3, 4, 5));1718function sum2() {19 let total = 0;20 for (let value of arguments) {21 total = total + value;22 }23 return total;24}2526console.log(sum2(1, 2, 3, 4, 5, 10));
The rest operator
1function sum(...args) {2 console.log(args);3 return args.reduce((a, b) => a + b);4}56console.log(sum(1, 2, 3, 4, 5));
Rest parameter must be last formal parameter. So we cannot have a parameter after using the rest operator.
Default Parameter
Whenever you want to give the function parameter a default value, make sure that parameter is the last parameter in the list, or give all the parameters after that a default value.
1function interest(principal, rate, years) {2 rate = rate || 3.5;3 years = years || 5;4 return ((principal * rate) / 100) * years;5}6console.log(interest(10000));78function interest(principal, rate = 3.5, years = 5) {9 return ((principal * rate) / 100) * years;10}11console.log(interest(10000));
getter setter
1const person = {2 firstname: 'Anish',3 secondname: 'Kumar',4 get fullName() {5 return `${this.firstname} ${this.secondname}`;6 },7 set fullName(value) {8 const parts = value.split(' ');9 this.firstname = parts[0];10 this.secondname = parts[1];11 },12};1314console.log(person.fullName);15console.log(person.firstname);16console.log(person.secondname);1718person.fullName = 'John smith';1920console.log(person.fullName);21console.log(person.firstname);22console.log(person.secondname);
Try Catch
1const person = {2 firstname: 'Anish',3 secondname: 'Kumar',4 get fullName() {5 return `${this.firstname} ${this.secondname}`;6 },7 set fullName(value) {8 if (typeof value !== 'string') {9 throw new Error('Value is not a string');10 }11 const parts = value.split(' ');12 if (parts.length !== 2) {13 throw new Error('Enter a first and second name');14 }15 this.firstname = parts[0];16 this.secondname = parts[1];17 },18};1920try {21 person.fullName = null;22} catch (e) {23 alert(e);24}
Scope
So a scope of a variable or a constant, determines where that variable or constant is accessible.
1{2 const name = 'ansih';3}45// console.log(name); //ReferenceError: name is not defined
1function start() {2 const message = 'hi';34 if (true) {5 const another = 'bye';6 }78 // console.log(another); //ReferenceError: another is not defined9}1011start();
1function start() {2 for (let i = 0; i < 10; i++) {3 console.log(i);4 }5 //console.log(i); //ReferenceError: i is not defined6}78start();
1const color = 'red'; //global scope23function start() {4 console.log(color);5}67function stop() {8 console.log(color);9}1011start();1213stop();
let vs var
When you declare a variable with var
. It's scope, is not limited to the block in which it's defined. It's limited to the function in which it's defined.
So before ES6, var
was the only way to declare variables and constants. Starting from ES6, also called ES2015, now we have two new keywords let
and const
, to define different variables and constants.
These two keywords create block scope variables, but var creates function scoped variables.
1function start() {2 for (let i = 0; i < 10; i++) {3 console.log(i);4 }5 //console.log(i); //ReferenceError: i is not defined6}78start();
1function start() {2 for (var i = 0; i < 10; i++) {3 console.log(i);4 }5 console.log(i);6}78start();
When we use var
, outside of a function, this creates a global variable and attaches that global variable to the window object in the browser. So in browsers we have this window object, which is a complex object with lots of proprties.
In contrast when we use the let
keyword to define a global variable, that global variable is not attached to the window object.
If a third party library also has a variable with the same name, that variable can override your variable.
1var color = 'red';2let age = 30;34//So technically this is a global function, it's attached to the window object and that is bad practice.5function sayHi() {6 console.log('HI');7}
this
when you use the new operator this new operator creates a new empty object and sets this in this constructor function to point to this empty object.
1const video = {2 title: 'a',3 play: function () {4 console.log(this);5 },6};78video.stop = function () {9 console.log(this);10};1112video.play();13video.stop();1415function playVideo() {16 console.log(this); // we are going to see the global object which is window in browsers and global in Node.17}18playVideo();1920function Video() {21 this.title = 'kumar';22 this.name = 'manish';23 console.log(this);24}2526const v = new Video();
1const video = {2 title: 'a',3 tags: ['a', 'b', 'c'],4 showTags() {5 this.tags.forEach(function (tag) {6 console.log(this, tag);7 });8 },9};1011// showTags function is just a regular function. It's not a method in the video object. So because this is a regular function, this references the global object12video.showTags();1314//for each method has two parameters,the first parameter is our callback function, the second parameter is thisArg? So we can pass an object here, and this will reference that object. For example, here I can pass a new object1516const video1 = {17 title: 'a',18 tags: ['a', 'b', 'c'],19 showTags() {20 this.tags.forEach(function (tag) {21 console.log(this, tag);22 }, this);23 },24};2526video1.showTags();
Changing this
1const video = {2 title: 'a',3 tags: ['a', 'b', 'c'],4 showTags() {5 const self = this;6 this.tags.forEach(function (tag) {7 console.log(self.title, tag);8 });9 },10};11video.showTags();
1function playVideo(a, b) {2 console.log(this);3}45playVideo();67playVideo.call({ title: 'call' }, 1, 2);89playVideo.apply({ title: 'apply' }, [1, 2]);1011fn = playVideo.bind({ title: 'bind' });12playVideo();13fn();
1const video = {2 title: 'a',3 tags: ['a', 'b', 'c'],4 showTags() {5 this.tags.forEach(6 function (tag) {7 console.log(this.title, tag);8 }.bind(this)9 );10 },11};12video.showTags();
Arrow functions
inherit this from the containing function.
1const video = {2 title: 'a',3 tags: ['a', 'b', 'c'],4 showTags() {5 this.tags.forEach((tag) => {6 console.log(this.title, tag);7 });8 },9};10video.showTags();
Array.isArray
1console.log(sum(1, 2, 3, 4));23function sum(...items) {4 return items.reduce((a, b) => a + b);5}67console.log(sum2([1, 2, 3, 4]));89function sum2(...items) {10 if (items.length === 1 && Array.isArray(items[0])) {11 items = items[0];12 }13 return items.reduce((a, b) => a + b);14}
calculate circle area
1const circle = {2 radius: 1,3 get area() {4 return Math.PI * this.radius * this.radius;5 },6};78console.log(circle.area);
What is the output of the following code?
1const b = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];23for (let i = 0; i < 10; i++) {4 setTimeout(() => console.log(b[i]), 1000);5}67for (var i = 0; i < 10; i++) {8 setTimeout(() => console.log(b[i]), 1000);9}
112233445566778899101011undefined12undefined13undefined14undefined15undefined16undefined17undefined18undefined19undefined20undefined
In JavaScript, how do you turn an Object into an Array []?
1let obj = { id: '1', name: 'user22', age: '26', work: 'programmer' };2//Method 1: Convert the keys to Array using - Object.keys()3console.log(Object.keys(obj));4// ["id", "name", "age", "work"]56// Method 2 Converts the Values to Array using - Object.values()7console.log(Object.values(obj));8// ["1", "user22r", "26", "programmer"]910// Method 3 Converts both keys and values using - Object.entries()11console.log(Object.entries(obj));12//[["id", "1"],["name", "user22"],["age", "26"],["work", “programmer"]]
Write the code to find the vowels
1const findVowels = (str) => {2 let count = 0;3 const vowels = ['a', 'e', 'i', 'o', 'u'];4 for (let char of str.toLowerCase()) {5 if (vowels.includes(char)) {6 count++;7 }8 }9 return count;10};
Write the code given If two strings are anagrams of one another, then return true.
1var firstWord = 'Deepak';2var secondWord = 'Aman';34isAnagram(firstWord, secondWord); // true56function isAnagram(one, two) {7 //Change both words to lowercase for case insensitivity..8 var a = one.toLowerCase();9 var b = two.toLowerCase();1011 // Sort the strings, then combine the array to a string. Examine the outcomes.12 a = a.split('').sort().join('');13 b = b.split('').sort().join('');1415 return a === b;16}
Write the code for dynamically inserting new components.
1<html>2 <head>3 <title>inserting new components dynamically</title>4 <script type="text/javascript">5 function addNode() {6 var newP = document.createElement('p');7 var textNode = document.createTextNode(' This is other node');8 newP.appendChild(textNode);9 document.getElementById('parent1').appendChild(newP);10 }11 </script>12 </head>13 <body>14 <p id="parent1">firstP</p>15 <p></p>16 </body>17</html>
Implement a function that returns an updated array with r right rotations on an array of integers a .Example:
1function rotateRight(arr, rotations) {2 if (rotations == 0) return arr;3 for (let i = 0; i < rotations; i++) {4 let element = arr.pop();5 arr.unshift(element);6 }7 return arr;8}9rotateRight([2, 3, 4, 5, 7], 3); // Return [4,5,7,2,3]10rotateRight([44, 1, 22, 111], 5); // Returns [111,44,1,22]
Write a function that performs binary search on a sorted array.
1function binarySearch(arr,value,startPos,endPos){2 if(startPos > endPos) return -1;34 let middleIndex = Math.floor(startPos+endPos)/2;56 if(arr[middleIndex] === value) return middleIndex;78 elsif(arr[middleIndex > value]){9 return binarySearch(arr,value,startPos,middleIndex-1);10 }11 else{12 return binarySearch(arr,value,middleIndex+1,endPos);13 }14}
Modify Code
1// Each time bigFunc is called, an array of size 700 is being created,2// Modify the code so that we don't create the same array again and again34function bigFunc(element) {5 let newArray = new Array(700).fill('♥');6 return newArray[element];7}89console.log(bigFunc(599)); // Array is created10console.log(bigFunc(670)); // Array is created again
1function bigFunc() {2 let newArray = new Array(700).fill('♥');3 return (element) => newArray[element];4}56let getElement = bigFunc(); // Array is created only once7getElement(599);8getElement(670);
Guess the output
1(function (a) {2 return (function () {3 console.log(a);4 a = 23;5 })();6})(45);
145
Guess the output
1(function (a) {2 return (function () {3 a = 23;4 console.log(a);5 })();6})(45);
123
Guess the output
1let hero = {2 powerLevel: 99,3 getPower() {4 return this.powerLevel;5 },6};78let getPower = hero.getPower;910let hero2 = { powerLevel: 42 };11console.log(getPower());12console.log(hero.getPower());13console.log(getPower.apply(hero2));
1undefined299342
Guess the output
1const a = function () {2 console.log(this);34 const b = {5 func1: function () {6 console.log(this);7 },8 };910 const c = {11 func2: () => {12 console.log(this);13 },14 };1516 b.func1();17 c.func2();18};1920a();
1global/window object2object "b"3global/window object
Guess the output
1const b = {2 name: 'Vivek',3 f: function () {4 var self = this;5 console.log(this.name);6 (function () {7 console.log(this.name);8 console.log(self.name);9 })();10 },11};12b.f();
1"Vivek"2undefined3"Vivek"
Guess the output
1var x = 23;23(function () {4 var x = 43;5 (function random() {6 x++;7 console.log(x);8 var x = 21;9 })();10})();
1NaN
Guess the output
random() function has functional scope since x is declared and hoisted in the functional scope.
Rewriting the random function will give a better idea about the output:
1function random() {2 var x; // x is hoisted3 x++; // x is not a number since it is not initialized yet4 console.log(x); // Outputs NaN5 x = 21; // Initialization of x6}
Guess the output
Adding objects as properties of another object should be done carefully. Writing x[y] = {name:”Vivek”} , is same as writing x[‘object Object’] = {name:”Vivek”} ,
While setting a property of an object, javascript coerces the parameter into a string. Therefore, since y is an object, it will be converted to ‘object Object’.
Both x[y] and x[z] are referencing the same property.
1let x = {},2 y = { name: 'Ronny' },3 z = { name: 'John' };4x[y] = { name: 'Vivek' };5x[z] = { name: 'Akki' };6console.log(x[y]);
1{ name: 'Akki' }
Guess the output
1function runFunc() {2 console.log('1' + 1);3 console.log('A' - 1);4 console.log(2 + '-2' + '2');5 console.log('Hello' - 'World' + 78);6 console.log('Hello' + '78');7}
1112NaN32-224NaN5Hello78
Guess the output
1let a = 0;2let b = false;3console.log(a == b);4console.log(a === b);
1true2false
Guess the output
1function func1() {2 setTimeout(() => {3 console.log(x);4 console.log(y);5 }, 3000);67 var x = 2;8 let y = 12;9}10func1();
12212
Outputs 2 and 12. Since, even though let variables are not hoisted, due to the async nature of javascript, the complete function code runs before the setTimeout function. Therefore, it has access to both x and y.
Guess the output
1function func2() {2 for (var i = 0; i < 3; i++) {3 setTimeout(() => console.log(i), 2000);4 }5}6func2();
132333
Outputs 3, three times since variable declared with var keyword does not have block scope. Also, inside the for loop, the variable i is incremented first and then checked.
Guess the output
1function(){2 setTimeout(()=> console.log(1),2000);3 console.log(2);4 setTimeout(()=> console.log(3),0);5 console.log(4);6 }7)();
12243341
Even though the second timeout function has a waiting time of zero seconds, the javascript engine always evaluates the setTimeout function using the Web API, and therefore, the complete function executes before the setTimeout function can execute.
What are the primitive data types in JavaScript?
- Boolean
- Undefined
- Null
- Number
- String
What is Object Destructuring?
1const classDetails = {2 strength: 78,3 benches: 39,4 blackBoard: 1,5};67const {8 strength: classStrength,9 benches: classBenches,10 blackBoard: classBlackBoard,11} = classDetails;1213console.log(classStrength); // Outputs 7814console.log(classBenches); // Outputs 3915console.log(classBlackBoard); // Outputs 11617const { strength: strength } = classDetails;18// The above line of code can be written as:19const { strength } = classDetails;
Weakmap
In javascript, Map is used to store key-value pairs. The key-value pairs can be of both primitive and non-primitive types. WeakMap is similar to Map with key differences:
- The keys and values in weakmap should always be an object.
- If there are no references to the object, the object will be garbage collected.
1const map1 = new Map();2map1.set('Value', 1);34const map2 = new WeakMap();5map2.set('Value', 2.3); // Throws an error67let obj = { name: 'Vivek' };8const map3 = new WeakMap();9map3.set(obj, { age: 23 });
WeakSet
In javascript, a Set is a collection of unique and ordered elements. Just like Set, WeakSet
is also a collection of unique and ordered elements with some key differences:
Weakset
contains only objects and no other type.
An object inside the weakset
is referenced weakly. This means, that if the object inside the weakset
does not have a reference, it will be garbage collected.
Unlike Set, WeakSet
only has three methods, add() , delete() and has() .
1const newSet = new Set([4, 5, 6, 7]);2console.log(newSet); // Outputs Set {4,5,6,7}34const newSet2 = new WeakSet([3, 4, 5]); //Throws an error56let obj1 = { message: 'Hello world' };7const newSet3 = new WeakSet([obj1]);8console.log(newSet3.has(obj1)); // true
What are generator functions?
Introduced in the ES6 version, generator functions are a special class of functions. They can be stopped midway and then continue from where they had stopped. Generator functions are declared with the function* keyword instead of the normal function keyword.
In normal functions, we use the return keyword to return a value and as soon as the return statement gets executed, the function execution stops:
1function normalFunc() {2 return 22;3 console.log(2); // This line of code does not get executed4}
In the case of generator functions, when called, they do not execute the code, instead, they return a generator object. This generator object handles the execution.
1function* genFunc() {2 yield 3;3 yield 4;4}5genFunc(); // Returns Object [Generator] {}
The generator object consists of a method called next(), this method when called, executes the code until the nearest yield statement, and returns the yield value.
For example, if we run the next() method on the above code:
1genFunc().next(); // Returns {value: 3, done:false}
As one can see the next method returns an object consisting of a value and done properties. Value property represents the yielded value. Done property tells us whether the function code is finished or not. (Returns true if finished).
What are classes in javascript?
Introduced in the ES6 version, classes are nothing but syntactic sugars for constructor functions. They provide a new way of declaring constructor functions in javascript. Below are the examples of how classes are declared and used:
1// Before ES6 version, using constructor functions2function Student(name, rollNumber, grade, section) {3 this.name = name;4 this.rollNumber = rollNumber;5 this.grade = grade;6 this.section = section;7}89// Way to add methods to a constructor function10Student.prototype.getDetails = function () {11 return 'Name: ${this.name}, Roll no: ${this.rollNumber}, Grade: ${this.grade}, Section:${this.section}';12};1314let student1 = new Student('Vivek', 354, '6th', 'A');15student1.getDetails();16// Returns Name: Vivek, Roll no:354, Grade: 6th, Section:A1718// ES6 version classes19class Student {20 constructor(name, rollNumber, grade, section) {21 this.name = name;22 this.rollNumber = rollNumber;23 this.grade = grade;24 this.section = section;25 }2627 // Methods can be directly added inside the class28 getDetails() {29 return 'Name: ${this.name}, Roll no: ${this.rollNumber}, Grade:${this.grade}, Section:${this.section}';30 }31}3233let student2 = new Student('Garry', 673, '7th', 'C');34student2.getDetails();35// Returns Name: Garry, Roll no:673, Grade: 7th, Section:C
37. What is the use of promises in javascript?
Promises are used to handle asynchronous operations in javascript.
Before promises, callbacks were used to handle asynchronous operations. But due to the limited functionality of callbacks, using multiple callbacks to handle asynchronous code can lead to unmanageable code.
Promise object has four states -
- Pending - Initial state of promise. This state represents that the promise has neither been fulfilled nor been rejected, it is in the pending state.
- Fulfilled - This state represents that the promise has been fulfilled, meaning the async operation is completed.
- Rejected - This state represents that the promise has been rejected for some reason, meaning the async operation has failed.
- Settled - This state represents that the promise has been either rejected or fulfilled.
resolve
is a function that will be called when the async operation has been successfully completed.
reject
is a function that will be called, when the async operation fails or if some error occurs.
Promises are used to handle asynchronous operations like server requests, for ease of understanding, we are using an operation to calculate the sum of three elements.
1function sumOfThreeElements(...elements) {2 return new Promise((resolve, reject) => {3 if (elements.length > 3) {4 reject('Only three elements or less are allowed');5 } else {6 let sum = 0;7 let i = 0;8 while (i < elements.length) {9 sum += elements[i];10 i++;11 }12 resolve('Sum has been calculated: ' + sum);13 }14 });15}1617sumOfThreeElements(4, 5, 6)18 .then((result) => console.log(result))19 .catch((error) => console.log(error));20// In the code above, the promise is fulfilled so the then() method gets executed2122sumOfThreeElements(7, 0, 33, 41)23 .then((result) => console.log(result))24 .catch((error) => console.log(error));25// In the code above, the promise is rejected hence the catch() method gets executed
What are arrow functions?
Arrow functions were introduced in the ES6 version of javascript. They provide us with a new and shorter syntax for declaring functions. Arrow functions can only be used as a function expression.
1// Traditional Function Expression2var add = function (a, b) {3 return a + b;4};56// Arrow Function Expression7var arrowAdd = (a, b) => a + b;
1var obj1 = {2 valueOfThis: function () {3 return this;4 },5};6var obj2 = {7 valueOfThis: () => {8 return this;9 },10};1112obj1.valueOfThis(); // Will return the object obj113obj2.valueOfThis(); // Will return window/global object
The biggest difference between the traditional function expression and the arrow function is the handling of this keyword. By general definition, this keyword always refers to the object that is calling the function. As you can see in the code above, obj1.valueOfThis() returns obj1 since this keyword refers to the object calling the function.
In the arrow functions, there is no binding of this keyword. This keyword inside an arrow function does not refer to the object calling it. It rather inherits its value from the parent scope which is the window object in this case. Therefore, in the code above, obj2.valueOfThis() returns the window object.
Which method is used to retrieve a character from a certain index?
The charAt() function of the JavaScript string finds a char element at the supplied index. The index number begins at 0 and continues up to n-1, Here n is the string length.
What is DOM? DOM stands for Document Object Model. DOM is a programming interface for HTML and XML documents.
When the browser tries to render an HTML document, it creates an object based on the HTML document called DOM. Using this DOM, we can manipulate or change various elements inside the HTML document.
Example of how HTML code gets converted to DOM:
What is the use of a constructor function in javascript?
Constructor functions are used to create objects in javascript.
If we want to create multiple objects having similar properties and methods, constructor functions are used.
Note- The name of a constructor function should always be written in Pascal Notation: every word should start with a capital letter.
1function Person(name, age, gender) {2 this.name = name;3 this.age = age;4 this.gender = gender;5}67var person1 = new Person('Vivek', 76, 'male');8console.log(person1);910var person2 = new Person('Courtney', 34, 'female');11console.log(person2);
26. What is recursion in a programming language?
1function computeSum(arr) {2 if (arr.length === 1) {3 return arr[0];4 } else {5 return arr.pop() + computeSum(arr);6 }7}8computeSum([7, 8, 9, 99]); // Returns 123
What is memoization?
1function addTo256(num) {2 return num + 256;3}4addTo256(20); // Returns 2765addTo256(40); // Returns 2966addTo256(20); // Returns 276
1function memoizedAddTo256() {2 var cache = {};34 return function (num) {5 if (num in cache) {6 console.log('cached value');7 return cache[num];8 } else {9 cache[num] = num + 256;10 return cache[num];11 }12 };13}14var memoizedFunc = memoizedAddTo256();1516memoizedFunc(20); // Normal return17memoizedFunc(20); // Cached return
23. What are callbacks?
A callback is a function that will be executed after another function gets executed. In javascript, functions are treated as first-class citizens, they can be used as an argument of another function, can be returned by another function, and can be used as a property of an object.
Functions that are used as an argument to another function are called callback functions. Example:
1function divideByHalf(sum) {2 console.log(Math.floor(sum / 2));3}45function multiplyBy2(sum) {6 console.log(sum * 2);7}89function operationOnSum(num1, num2, operation) {10 var sum = num1 + num2;11 operation(sum);12}1314operationOnSum(3, 3, divideByHalf); // Outputs 31516operationOnSum(5, 5, multiplyBy2); // Outputs 20
Explain Closures in JavaScript.
Closures are an ability of a function to remember the variables and functions that are declared in its outer scope.
1function randomFunc() {2 var obj1 = { name: 'Vivian', age: 45 };34 return function () {5 console.log(obj1.name + ' is ' + 'awesome'); // Has access to obj1 even when the randomFunc function is executed6 };7}89var initialiseClosure = randomFunc(); // Returns a function1011initialiseClosure();
When the function randomFunc() runs, it seems that the returning function is using the variable obj1 inside it:
Therefore randomFunc(), instead of destroying the value of obj1 after execution, saves the value in the memory for further reference. This is the reason why the returning function is able to use the variable declared in the outer scope even after the function is already executed.
This ability of a function to store a variable for further reference even after it is executed is called Closure.
Explain Scope and Scope Chain in javascript.
Scope in JS determines the accessibility of variables and functions at various parts of one’s code.
In general terms, the scope will let us know at a given part of code, what are variables and functions we can or cannot access.
There are three types of scopes in JS:
- Global Scope
- Local or Function Scope
- Block Scope
Global Scope
: Variables or functions declared in the global namespace have global scope, which means all the variables and functions having global scope can be accessed from anywhere inside the code.
1var globalVariable = 'Hello world';23function sendMessage() {4 return globalVariable; // can access globalVariable since it's written in global space5}6function sendMessage2() {7 return sendMessage(); // Can access sendMessage function since it's written in global space8}9sendMessage2(); // Returns “Hello world”
Function Scope
: Any variables or functions declared inside a function have local/function scope, which means that all the variables and functions declared inside a function, can be accessed from within the function and not outside of it.
1function awesomeFunction() {2 var a = 2;34 var multiplyBy2 = function () {5 console.log(a * 2); // Can access variable "a" since a and multiplyBy2 both are written inside the same function6 };7}8console.log(a); // Throws reference error since a is written in local scope and cannot be accessed outside910multiplyBy2(); // Throws reference error since multiplyBy2 is written in local scope
Block Scope
: Block scope is related to the variables declared using let and const. Variables declared with var do not have block scope. Block scope tells us that any variable declared inside a block { }, can be accessed only inside that block and cannot be accessed outside of it.
1{2 let x = 45;3}45console.log(x); // Gives reference error since x cannot be accessed outside of the block67for (let i = 0; i < 2; i++) {8 // do something9}1011console.log(i); // Gives reference error since i cannot be accessed outside of the for loop block
Scope Chain
: JavaScript engine also uses Scope to find variables. Let’s understand that using an example:
1var y = 24;23function favFunction() {4 var x = 667;5 var anotherFavFunction = function () {6 console.log(x); // Does not find x inside anotherFavFunction, so looks for variable inside favFunction, outputs 6677 };89 var yetAnotherFavFunction = function () {10 console.log(y); // Does not find y inside yetAnotherFavFunction, so looks for variable inside favFunction and does not find it, so looks for variable in global scope, finds it and outputs 2411 };1213 anotherFavFunction();14 yetAnotherFavFunction();15}16favFunction();
As you can see in the code above, if the javascript engine does not find the variable in local scope, it tries to check for the variable in the outer scope. If the variable does not exist in the outer scope, it tries to find the variable in the global scope.
If the variable is not found in the global space as well, a reference error is thrown.
What is currying in JavaScript?
Currying is an advanced technique to transform a function of arguments n, to n functions of one or fewer arguments.
1function add(a) {2 return function (b) {3 return a + b;4 };5}67add(3)(4);
1function multiply(a, b) {2 return a * b;3}45function currying(fn) {6 return function (a) {7 return function (b) {8 return fn(a, b);9 };10 };11}1213var curriedMultiply = currying(multiply);1415multiply(4, 3); // Returns 121617curriedMultiply(4)(3); // Also re
Explain this keyword.
1function doSomething() {2 console.log(this);3}45doSomething();
Since the function is invoked in the global context, the function is a property of the global object. Therefore, the output of the above code will be the global object.
1var obj = {2 name: 'vivek',3 getName: function () {4 console.log(this.name);5 },6};78obj.getName();
In the above code, at the time of invocation, the getName function is a property of the object obj , therefore, this keyword will refer to the object obj, and hence the output will be “vivek”.
1var obj = {2 name: 'vivek',3 getName: function () {4 console.log(this.name);5 },6};78var getName = obj.getName;910var obj2 = { name: 'akshay', getName };11obj2.getName();
The output will be “akshay”.
Although the getName function is declared inside the object obj, at the time of invocation, getName() is a property of obj2, therefore the “this” keyword will refer to obj2.
1var obj1 = {2 address: 'Mumbai,India',3 getAddress: function () {4 console.log(this.address);5 },6};78var getAddress = obj1.getAddress;9var obj2 = { name: 'akshay' };10obj2.getAddress();
The output will be an error.
Although in the code above, this keyword refers to the object obj2, obj2 does not have the property address, hence the getAddress function throws an error.
Explain Higher Order Functions in javascript.
Functions that operate on other functions, either by taking them as arguments or by returning them, are called higher-order functions.
1function higherOrder(fn) {2 fn();3}45higherOrder(function () {6 console.log('Hello world');7});8function higherOrder2() {9 return function () {10 return 'Do something';11 };12}13var x = higherOrder2();14x(); // Returns "Do something"
What do you mean by strict mode in javascript and characteristics of javascript strict-mode?
In ECMAScript 5, a new feature called JavaScript Strict Mode allows you to write a code or a function in a "strict" operational environment. In most cases, this language is 'not particularly severe' when it comes to throwing errors. In 'Strict mode,' however, all forms of errors, including silent errors, will be thrown. As a result, debugging becomes a lot simpler. Thus programmer's chances of making an error are lowered.
Characteristics of strict mode in javascript
- Duplicate arguments are not allowed by developers.
- In strict mode, you won't be able to use the JavaScript keyword as a parameter or function name.
- The 'use strict' keyword is used to define strict mode at the start of the script. Strict mode is supported by all browsers.
- Engineers will not be allowed to create global variables in 'Strict Mode.
What is an Immediately Invoked Function in JavaScript?
Syntax of IIFE :
1(function () {2 // Do something;3})();
To understand IIFE, we need to understand the two sets of parentheses that are added while creating an IIFE :
The first set of parenthesis:
1(function () {2 //Do something;3});
While executing javascript code, whenever the compiler sees the word “function”, it assumes that we are declaring a function in the code. Therefore, if we do not use the first set of parentheses, the compiler throws an error because it thinks we are declaring a function, and by the syntax of declaring a function, a function should always have a name.
1function() {2 //Do something;3}4// Compiler gives an error since the syntax of declaring a function is wrong in the code above.
To remove this error, we add the first set of parenthesis that tells the compiler that the function is not a function declaration, instead, it’s a function expression.
The second set of parenthesis:
1(function () {2 //Do something;3})();
From the definition of an IIFE, we know that our code should run as soon as it is defined. A function runs only when it is invoked. If we do not invoke the function, the function declaration is returned:
1(function () {2 // Do something;3});45// Returns the function declaration
Therefore to invoke the function, we use the second set of parenthesis.
Explain passed by value and passed by reference.
In JavaScript, primitive data types are passed by value and non-primitive data types are passed by reference.
1var y = 234;2var z = y;
In the above example, the assign operator knows that the value assigned to y is a primitive type (number type in this case), so when the second line code executes, where the value of y is assigned to z, the assign operator takes the value of y (234) and allocates a new space in the memory and returns the address. Therefore, variable z is not pointing to the location of variable y, instead, it is pointing to a new location in the memory.
1var obj = { name: 'Vivek', surname: 'Bisht' };2var obj2 = obj;
In the above example, the assign operator directly passes the location of the variable obj to the variable obj2. In other words, the reference of the variable obj is passed to the variable obj2.
From the above example, we can see that while passing non-primitive data types, the assign operator directly passes the address (reference).
Therefore, non-primitive data types are always passed by reference.
What is NaN property in JavaScript?
NaN property represents the “Not-a-Number” value. It indicates a value that is not a legal number.
typeof of NaN will return a Number.
To check if a value is NaN, we use the isNaN() function,
Note- isNaN() function converts the given value to a Number type, and then equates to NaN.
1isNaN('Hello'); // Returns true2isNaN(345); // Returns false3isNaN('1'); // Returns false, since '1' is converted to Number type which results in 0 ( a number)4isNaN(true); // Returns false, since true converted to Number type results in 1 ( a number)5isNaN(false); // Returns false6isNaN(undefined); // Returns true
Is javascript a statically typed or a dynamically typed language?
JavaScript is a dynamically typed language. In a dynamically typed language, the type of a variable is checked during run-time in contrast to a statically typed language, where the type of a variable is checked during compile-time.
What is a potential pitfall with using typeof bar === "object" to determine if bar is an object? How can this pitfall be avoided?
Although typeof bar === "object" is a reliable way of checking if bar is an object, the surprising gotcha in JavaScript is that null is also considered an object!
1var bar = null;2console.log(typeof bar === 'object'); // logs true!
the problem can easily be avoided by also checking if bar is null:
1console.log(bar !== null && typeof bar === 'object'); // logs false
First, the above solution will return false if bar is a function. In most cases, this is the desired behavior, but in situations where you want to also return true for functions, you could amend the above solution to be:
1console.log(2 bar !== null && (typeof bar === 'object' || typeof bar === 'function')3);
However, there’s one other alternative that returns false for nulls, arrays, and functions, but true for objects:
1console.log(bar !== null && bar.constructor === Object);
Define output
1(function () {2 var a = (b = 3);3})();45console.log('a defined? ' + (typeof a !== 'undefined'));6console.log('b defined? ' + (typeof b !== 'undefined'));
Since both a and b are defined within the enclosing scope of the function, and since the line they are on begins with the var keyword, most JavaScript developers would expect typeof a and typeof b to both be undefined
But in fact, var a = b = 3; is actually shorthand for:
1b = 3;2var a = b;
As a result (if you are not using strict mode), the output of the code snippet would be:
1a defined? false2b defined? true
But how can b be defined outside of the scope of the enclosing function? Well, since the statement var a = b = 3; is shorthand for the statements b = 3; and var a = b;, b ends up being a global variable (since it is not preceded by the var keyword) and is therefore still in scope even outside of the enclosing function.
Note that, in strict mode (i.e., with use strict), the statement var a = b = 3; will generate a runtime error of ReferenceError: b is not defined
define output
1var myObject = {2 foo: 'bar',3 func: function () {4 var self = this;5 console.log('outer func: this.foo = ' + this.foo);6 console.log('outer func: self.foo = ' + self.foo);7 (function () {8 console.log('inner func: this.foo = ' + this.foo);9 console.log('inner func: self.foo = ' + self.foo);10 })();11 },12};13myObject.func();
1outer func: this.foo = bar2outer func: self.foo = bar3inner func: this.foo = undefined4inner func: self.foo = bar
In the outer function, both this and self refer to myObject and therefore both can properly reference and access foo.
In the inner function, though, this no longer refers to myObject. As a result, this.foo is undefined in the inner function, whereas the reference to the local variable self remains in scope and is accessible there.
Consider the two functions below. Will they both return the same thing? Why or why not?
1function foo1() {2 return {3 bar: 'hello',4 };5}67function foo2() {8 return;9 {10 bar: 'hello';11 }12}
Surprisingly, these two functions will not return the same thing. Rather:
1console.log('foo1 returns:');2console.log(foo1());3console.log('foo2 returns:');4console.log(foo2());
will yield:
1foo1 returns:2Object {bar: "hello"}3foo2 returns:4undefined
Not only is this surprising, but what makes this particularly gnarly is that foo2() returns undefined without any error being thrown.
The reason for this has to do with the fact that semicolons are technically optional in JavaScript (although omitting them is generally really bad form). As a result, when the line containing the return statement (with nothing else on the line) is encountered in foo2(), a semicolon is automatically inserted immediately after the return statement.
No error is thrown since the remainder of the code is perfectly valid, even though it doesn’t ever get invoked or do anything
In what order will the numbers 1-4 be logged to the console when the code below is executed? Why?
1(function () {2 console.log(1);3 setTimeout(function () {4 console.log(2);5 }, 1000);6 setTimeout(function () {7 console.log(3);8 }, 0);9 console.log(4);10})();
The values will be logged in the following order:
11243342
Write a simple function (less than 160 characters) that returns a boolean indicating whether or not a string is a palindrome.
1function isPalindrome(str) {2 return str == str.split('').reverse().join('');3}45console.log(isPalindrome('anishhsina'));
Write a sum method which will work properly when invoked using either syntax below
1function sum(x) {2 if (arguments.length == 2) {3 return arguments[0] + arguments[1];4 } else {5 return function (y) {6 return x + y;7 };8 }9}
In JavaScript, functions provide access to an arguments object which provides access to the actual arguments passed to a function. This enables us to use the length property to determine at runtime the number of arguments passed to the function.
1function sum(x, y) {2 if (y !== undefined) {3 return x + y;4 } else {5 return function (y) {6 return x + y;7 };8 }9}
When a function is invoked, JavaScript does not require the number of arguments to match the number of arguments in the function definition. If the number of arguments passed exceeds the number of arguments in the function definition, the excess arguments will simply be ignored. On the other hand, if the number of arguments passed is less than the number of arguments in the function definition, the missing arguments will have a value of undefined when referenced within the function. So, in the above example, by simply checking if the 2nd argument is undefined, we can determine which way the function was invoked and proceed accordingly.
Map over an array and reduce it to array
Hoisting
1console.log(foo);2foo = 1;
Above will throw an error.
1console.log(foo);2var foo = 2;
This is print undefined
. var
declaration is bubbled to the top. This is called Hoisting. Above will get converted to
1var foo;2console.log(foo);3foo = 2;
This will how it will be interpreted by javascript.
1foo = 2;2console.log(foo);3var foo = 3;
Above will print 2
. Above will be interpreted as
1var foo;2foo = 2;3console.log(foo);4foo = 3;
1foo();23function foo() {4 console.log('anish');5}
This will be interpreted as
1function foo() {2 console.log('anish');3}45foo();
Functions are hoisted to the top.
1console.log(a);23const a = 1;
This will throw an error. const
and let
doesn't get bubbled to the top.