Here's the list of topics that will be covered :
- Normal Functions & Arrow Functions,
- Polyfills of map, filter and reduce,
- Closures,
- Currying in JavaScript,
- Objects in JavaScript,
- this-keyword,
- call, bind and apply,
- Polyfills of call, bind and apply.
- Promises,
- Debouncing and throttling implementation,
- Event Propogation(Event capturing, event bubbling, event target and event Delegation).
Answer
function definition or function declaration or function statement means defining a function using normal function syntax.
function name(){
console.log("saurabh");
}
Answer
A function assigned to a variable is called as function expression.
const name = function (){
console.log("saurabh");
}
let about = () => {
console.log("Frontend engineer");
}
Answer
function statements can be called before initialization. function expression can not be called before initialization, they behave as normal variables syntax(const, let and var).
// behaves normally
funcStatement();
function funcStatement(){
console.log("hello");
}
// behaves as let var const
funcExpression();
let funcExpression = function (){
console.log("this will give ReferenceError");
}
Answer
This is what the TDZ is: the term to describe the state where variables are un-reachable. They are in scope, but they aren't declared.
The let and const variables exist in the TDZ from the start of their enclosing scope until they are declared.
// This is the temporal dead zone for the name and age variable!
// ReferenceError: cannot acccess name before initialization.
console.log(name);
let name = "saurabh";
// This is the temporal dead zone for the age variable!
// This is the temporal dead zone for the age variable!
let age = 25; // Whew, we got there! No more TDZ
console.log(age);
Answer
Functions which can be treated as value(passing function as arguments or return them as value) is called as first class functions.
function square(num){
return num*num;
}
function display(callback){
console.log('square is a first class function: '+ callback(4));
}
display(square)
Answer
IIFE is a JavaScript function that runs as soon as it is defined.
(function (num){
console.log(num*num);
})(4);
(function (x){
return (function(y){
console.log(x);
})(2);
})(1)
- A:
2
- B:
1
- C:
ReferenceError
- D:
undefined
Answer
When the outer function is called with the argument 1
, it immediately calls the inner function with the argument 2
. The inner function then logs the value of x
to the console, which is 1
.
let count = 0;
(function () {
if(count === 0){
let count = 1;
console.log(count);
}
console.log(count);
})();
- A:
1
and1
- B:
0
and1
- C:
1
and0
- D:
0
and0
Hint: variable hoisting
var name = 'javascript';
var display = function () {
console.log(name);
var name = 'saurabh';
}
display();
- A:
javascript
- B:
saurabh
- C:
undefined
- D:
ReferenceError
Answer
When the display
function is called, it first tries to log the value of the local variable name
. However, since there is a declaration of a new variable name
within the function, it creates a new local variable name
that shadows the outer variable.
Since the new local variable name
is declared but not yet assigned a value at the time of the console.log
statement, it will output undefined
.
function display(a, b, ...rest) {
console.log(a, b, rest);
}
display(23, 3, 4, 7, 8);
- A:
23 3 [4, 7, 8]
- B:
ReferenceError
- C:
23 3 4, 7, 8
- D:
23 3 4
Answer
last parameter used with ...
is called rest operator. Rest operator stores rest of the params in array.
function display(a, b) {
console.log(a+b);
}
let values = [5, 6]
display(values[0], values[1]);
display(...values);
- A:
11
andReferenceError
- B:
ReferenceError
and11
- C:
5
and6
- D:
11
and11
Answer
Here ...
is used as spread operator. Spread operator spreads the array/object values.
function display(a, ...rest, b) {
console.log(a, rest, b);
}
display(23, 3, 4, 7, 8);
- A:
23 [3, 4, 7] 8
- B:
SyntaxError: Rest parameter must be last formal parameter
- C:
23 3 4, 7, 8
- D:
23 3 8
function display(...nums) {
let ans = 0;
for(const i of nums)ans += i;
return ans;
}
console.log(display(1, 2, 3, 4, 5));
- A:
0
- B:
15
- C:
10
- D:
[1, 2, 3, 4, 5]
Answer
we are looping through the nums array and adding all the elements then returning the sum
Answer
// !NOTE: this-keyword is covered later
const arr = [1, 2, 3, 4];
Array.prototype.myMap = function(callback){
let res = [];
for(let i=0;i<this.length;++i){
res.push(callback(this[i], i, this));
}
return res;
}
const ans = arr.myMap((item, index, ar) => item * 2);
console.log(ans); // [2, 4, 6, 8]
Answer
const arr = [1, 2, 3, 4];
Array.prototype.myFilter = function(callback){
let res = [];
for(let i=0;i<this.length;++i){
if(callback(this[i], i, this))res.push(this[i]);
}
return res;
}
const ans = arr.myFilter((item, index, ar) => item > 2);
console.log(ans); // [3, 4]
Answer
Array.prototype.myReduce = function(callback, initialVal) {
if (!this) throw new Error("myReduce is called on null or undefined");
if (typeof callback !== 'function') throw new Error("callback is not a function");
let len = this.length,
k = 0,
value = undefined;
if (initialVal !== undefined) value = initialVal;
else {
while(k<len && !(k in this)){
k++;
}
if(k >= len)throw new Error("reduce is called on empty array with no initial value")
value = this[k++];
}
for (; k < len; ++k) {
value = callback(value, this[k], k, this);
}
return value;
}
const arr = [1, 2, 3, 4];
console.log(arr.myReduce((acc, cur, ind, arr) => acc + cur, 0)); // 15
let students = [
{ name: "saurabh", age : 22, marks: 80},
{ name: 'jenny', age:15, marks:69},
{ name: 'Rinku', age:16, marks:35},
{ name: 'preet', age:7, marks:55},
];
Answer
const students = [
{ name: "saurabh", age : 22, marks: 80},
{ name: 'jenny', age:15, marks:69},
{ name: 'Rinku', age:16, marks:35},
{ name: 'preet', age:7, marks:55},
];
function upperCaseNames(students){
let ans = students.map((item)=> item.name.toUpperCase())
return ans;
}
console.log(upperCaseNames(students)) // ['SAURABH', 'JENNY', 'RINKU', 'PREET']
let students = [
{ name: "saurabh", age : 22, marks: 80},
{ name: 'jenny', age:15, marks:69},
{ name: 'Rinku', age:16, marks:35},
{ name: 'preet', age:7, marks:55},
];
Answer
const students = [
{ name: "saurabh", age : 22, marks: 80},
{ name: 'jenny', age:15, marks:69},
{ name: 'Rinku', age:16, marks:35},
{ name: 'preet', age:7, marks:55},
];
function toppers(students){
let ans = students.filter((item)=> item.marks >= 60)
return ans;
}
console.log(toppers(students))
// [{ name: "saurabh", age : 22, marks: 80}, { name: 'jenny', age:15, marks:69}]
Answer
A closure is the combination of a function bundled together(enclosed) with references to its surrounding state(the lexical environment).
var addSix = createBase(6);
addSix(10); //16
addSix(21); //27
Answer
function createBase(a){
return function(b){
console.log(a+b);
}
};
var addSix = createBase(6);
addSix(10); //16
addSix(21); //27
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 1);
}
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 1);
}
- A:
0 1 2
and0 1 2
- B:
0 1 2
and3 3 3
- C:
3 3 3
and0 1 2
Answer
Because of the event queue in JavaScript, the setTimeout
callback function is called after the loop has been executed. Since the variable i
in the first loop was declared using the var
keyword, this value was global. During the loop, we incremented the value of i
by 1 each time, using the unary operator ++
. By the time the setTimeout
callback function was invoked, i
was equal to 3
in the first example.
In the second loop, the variable i
was declared using the let
keyword: variables declared with the let
(and const
) keyword are block-scoped (a block is anything between { }
). During each iteration, i
will have a new value, and each value is scoped inside the loop.
Hint: use closure
function counter(){
// write your logic here...
return { add, retrive };
}
const { add, retrive } = counter();
add(1)
add(2)
add(3)
add(4);
console.log(retrive()); // 10
Answer
function counter(){
let _counter = 0;
function add(i) {
_counter += i;
}
function retrive(){
return "Counter value is: "+_counter;
}
return { add, retrive };
}
const { add, retrive } = counter();
add(1)
add(2)
add(3)
add(4);
console.log(retrive()); // 10
22. Write function that runs only once, if called more than once than print "cannot call more than once" in console.
function l(){
return function(){
}
};
let closure = l();
closure() // final execution
closure() // cannot call more than once
closure() // cannot call more than once
closure() // cannot call more than once
Answer
function l(){
let called=0;
return function(){
if(called > 0){
console.log("cannot call more than once")
}else{
console.log('final execution.');
called++;
}
}
};
let closure = l();
closure() // final execution.
closure() // cannot call more than once
closure() // cannot call more than once
closure() // cannot call more than once
Answer
Currying a function is a technique, in which a function accept one argument at a time and return a new function that accept the next argument
NOTE: In currying number of argument should be equal to number of function returned.
function sum(a){
// write your logic here...
}
sum(2)(6)(1) // 9
Answer
function sum(a){
return function(b){
return function(c){
console.log(a+b+c);
}
}
};
sum(2)(6)(1) // 9
Answer