It's a book about frontend interview question. We hope that it will help all javascript developers to prepare for a technical job interview.
- This Book will be completed by September 2018 and then it will be available to buy. If you want me to sent an early copy of this book, please add your name and email address in google form here Google Form.
- If you don't want to wait, you can buy Yuri's JavaScript Flashcards, a set of frontend interview questions sorted by popularity among the interviewers printed on beautiful poker-size flashcards.
In JavaScript if you try to use a variable that doesn't exist and has not been declared, then JavaScript will throw an error var name is not defined
and the script will stop execute thereafter. But If you use typeof undeclared_variable
then it will return undefined
.
Before starting further discussion let's understand the difference between declaration and definition.
var x
is a declaration because you are not defining what value it holds yet, but you are declaring its existence and the need for memory allocation.
var x; // declaring x
console.log(x); //output: undefined
var x = 1
is both declaration and definition (also we can say we are doing initialisation), Here declaration and assignment of value happen inline for variable x, In JavaScript every variable declaration and function declaration brings to the top of its current scope in which it's declared then assignment happen in order this term is called hoisting
.
A variable can be declared but not defined. When we try to access it, It will result undefined
.
var x; // Declaration
if(typeof x === 'undefined') // Will return true
A variable can be neither declared nor defined. When we try to reference such variable then the result will be not defined
.
console.log(y); // Output: ReferenceError: y is not defined
http://stackoverflow.com/questions/20822022/javascript-variable-definition-declaration
var y = 1;
if (function f() {}) {
y += typeof f;
}
console.log(y);
The code above would give the output 1undefined
. inside if
statement we have function f(){}
. Here's it's a function expression, not function statement, which is why f is not a variable.
As a reminder, function expression is something like this:
var myFunc1 = new function() {}
var myFunc2 = new function whatever() {} // whatever is not a variable here
A function statement is something like this:
function myFunc3() {}
You can read about function expressions and function statements on MDN.
One of the drawback of creating a private method in JavaScript is that they are very memory inefficient because a new copy of the method would be created for each instance.
var Employee = function (name, company, salary) {
this.name = name || "";
this.company = company || "";
this.salary = salary || 5000;
// Private method
var increaseSalary = function () {
this.salary = this.salary + 1000;
};
};
// adding the method to Employee's prototype
Employee.prototype.displayIncreasedSalary = function() {
increaseSalary();
console.log(this.salary);
};
// Creating three Employee objects
var emp1 = new Employee("John","Pluto",3000);
var emp2 = new Employee("Merry","Pluto",2000);
var emp3 = new Employee("Ren","Pluto",2500);
Here each instance variable emp1
, emp2
, emp3
has own copy of increaseSalary private method. However the displayIncreasedSalary
will only be added once to an object Employee.prototype
.
So as recommendation don't go for a private method unless it's necessary.
A closure is a function defined inside another function (called parent function) and has access to the variable which is declared and defined in parent function scope.
The closure has access to the variable in three scopes:
- Variable declared in his own scope
- Variable declared in parent function scope
- Variable declared in the global namespace
var globalVar = "abc";
// Parent self invoking function
(function outerFunction (outerArg) { // begin of scope outerFunction
// Variable declared in outerFunction function scope
var outerFuncVar = 'x';
// Closure self-invoking function
(function innerFunction (innerArg) { // begin of scope innerFunction
// variable declared in innerFunction function scope
var innerFuncVar = "y";
console.log(
"outerArg = " + outerArg + "\n" +
"outerFuncVar = " + outerFuncVar + "\n" +
"innerArg = " + innerArg + "\n" +
"innerFuncVar = " + innerFuncVar + "\n" +
"globalVar = " + globalVar);
// end of scope innerFunction
})(5); // Pass 5 as parameter
// end of scope outerFunction
})(7); // Pass 7 as parameter
innerFunction
is closure which is defined inside outerFunction
and has access to all variable which is declared and defined in outerFunction scope. In addition to this function defined inside the function as closure has access to the variable which is declared in global namespace
.
Output of above code would be:
outerArg = 7
outerFuncVar = x
innerArg = 5
innerFuncVar = y
globalVar = abc
console.log(mul(2)(3)(4)); // output : 24
console.log(mul(4)(3)(4)); // output : 48
Below is the code followed by the explanation of how it works:
function mul (x) {
return function (y) { // anonymous function
return function (z) { // anonymous function
return x * y * z;
};
};
}
Here the mul
function accepts the first argument and returns the anonymous function which takes the second parameter and returns the anonymous function which takes the third parameter and returns the multiplication of arguments which is being passed in successive
In Javascript function defined inside has access to outer function variable and function is the first class object so it can be returned by the function as well and passed as an argument in another function.
- A function is an instance of the Object type
- A function can have properties and has a link back to its constructor method
- A function can be stored as variable
- A function can be pass as a parameter to another function
- A function can be returned from another function
For instance:
var arrayList = ['a', 'b', 'c', 'd', 'e', 'f'];
How can we empty the array above?
There are a couple of ways by which we can empty an array, So let's discuss all the possible way by which we can empty an array.
arrayList = [];
The code above will set the variable arrayList
to a new empty array. This is recommended if you don't have references to the original array arrayList
anywhere else because It will actually create a new empty array. You should be careful with this way of empty the array, because if you have referenced this array from another variable, then the original reference array will remain unchanged, Only use this way if you have only referenced the array by its original variable arrayList
.
For Instance:
var arrayList = ['a', 'b', 'c', 'd', 'e', 'f']; // Created array
var anotherArrayList = arrayList; // Referenced arrayList by another variable
arrayList = []; // Empty the array
console.log(anotherArrayList); // Output ['a', 'b', 'c', 'd', 'e', 'f']
arrayList.length = 0;
The code above will clear the existing array by setting its length to 0. This way of emptying an array will also update all the reference variables that point to the original array.
For Instance:
var arrayList = ['a', 'b', 'c', 'd', 'e', 'f']; // Created array
var anotherArrayList = arrayList; // Referenced arrayList by another variable
arrayList.length = 0; // Empty the array by setting length to 0
console.log(anotherArrayList); // Output []
arrayList.splice(0, arrayList.length);
Above implementation will also work perfectly. This way of empty the array will also update all the references of the original array.
var arrayList = ['a', 'b', 'c', 'd', 'e', 'f']; // Created array
var anotherArrayList = arrayList; // Referenced arrayList by another variable
arrayList.splice(0, arrayList.length); // Empty the array by setting length to 0
console.log(anotherArrayList); // Output []
while(arrayList.length) {
arrayList.pop();
}
Above implementation can also empty the array. But not recommended to use often.
The best way to find whether an object is instance of a particular class or not using toString
method from Object.prototype
var arrayList = [1 , 2, 3];
One of the best use cases of type checking of an object is when we do method overloading in JavaScript. To understand this, let's say we have a method called greet
which can take a single string and also a list of strings. To make our greet
method workable in both situation we need to know what kind of parameter is being passed: is it single value or list of values?
function greet(param) {
if() {
// here have to check whether param is array or not
}
else {
}
}
However, in the above implementation it might not necessary to check the type of the array, we can check for single value string and put array logic code in else block, let see below code for the same.
function greet(param) {
if(typeof param === 'string') {
}
else {
// If param is of type array then this block of code would execute
}
}
Now it's fine we can go with the previous two implementations, but when we have a situation like a parameter can be single value
, array
, and object
type then we will be in trouble.
Coming back to checking the type of an object, As we mentioned that we can use Object.prototype.toString
if(Object.prototype.toString.call(arrayList) === '[object Array]') {
console.log('Array!');
}
If you are using jQuery
then you can also used jQuery isArray
method:
if($.isArray(arrayList)) {
console.log('Array');
} else {
console.log('Not an array');
}
FYI jQuery uses Object.prototype.toString.call
internally to check whether an object is an array or not.
In modern browser, you can also use:
Array.isArray(arrayList);
Array.isArray
is supported by Chrome 5, Firefox 4.0, IE 9, Opera 10.5 and Safari 5
var output = (function(x) {
delete x;
return x;
})(0);
console.log(output);
The code above will output 0
as output. delete
operator is used to delete a property from an object. Here x
is not an object it's local variable. delete
operator doesn't affect local variables.
var x = 1;
var output = (function() {
delete x;
return x;
})();
console.log(output);
The code above will output 1
as output. delete
operator is used to delete a property from an object. Here x
is not an object it's global variable of type number
.
var x = { foo : 1};
var output = (function() {
delete x.foo;
return x.foo;
})();
console.log(output);
The code above will output undefined
as output. delete
operator is used to delete a property from an object. Here x
is an object which has foo as a property and from a self-invoking function, we are deleting the foo
property of object x
and after deletion, we are trying to reference deleted property foo
which result undefined
.
var Employee = {
company: 'xyz'
}
var emp1 = Object.create(Employee);
delete emp1.company
console.log(emp1.company);
The code above will output xyz
as output. Here emp1
object got company as prototype property. delete operator doesn't delete prototype property.
emp1
object doesn't have company as its own property. you can test it console.log(emp1.hasOwnProperty('company')); //output : false
However, we can delete company property directly from Employee
object using delete Employee.company
or we can also delete from emp1
object using __proto__
property delete emp1.__proto__.company
.
var trees = ["redwood", "bay", "cedar", "oak", "maple"];
delete trees[3];
- When you run the code above and do
console.log(trees);
in chrome developer console then you will get["redwood", "bay", "cedar", undefined Ă— 1, "maple"]
. - In the recent versions of Chrome you will see the word
empty
ofundefined x 1
. - When you run the same code in Firefox browser console then you will get
["redwood", "bay", "cedar", undefined, "maple"]
Clearly we can see that Chrome has its own way of displaying uninitialized index in arrays. However when you check trees[3] === undefined
in any browser you will get similar output as true
.
Note: Please remember that you need not check for the uninitialized index of the array in trees[3] === 'undefined Ă— 1'
it will give an error because 'undefined Ă— 1'
this is just way of displaying an uninitialized index of an array in chrome.
var trees = ["xyz", "xxxx", "test", "ryan", "apple"];
delete trees[3];
console.log(trees.length);
The code above will output 5
as output. When we used delete
operator for deleting an array element then, the array length is not affected by this. This holds even if you deleted all elements of an array using delete
operator.
So when delete operator removes an array element that deleted element is no longer present in the array. In place of value at deleted index undefined x 1
in chrome and undefined
is placed at the index. If you do console.log(trees)
output ["xyz", "xxxx", "test", undefined Ă— 1, "apple"]
in Chrome and in Firefox ["xyz", "xxxx", "test", undefined, "apple"]
.
var bar = true;
console.log(bar + 0);
console.log(bar + "xyz");
console.log(bar + true);
console.log(bar + false);
The code above will output 1, "truexyz", 2, 1
as output. Here's a general guideline for the plus operator:
- Number + Number -> Addition
- Boolea 341A n + Number -> Addition
- Number + String -> Concatenation
- String + Boolean -> Concatenation
- String + String -> Concatenation
var z = 1, y = z = typeof y;
console.log(y);
The code above will print string "undefined"
as output. According to associativity rule operator with the same precedence are processed based on their associativity property of operator. Here associativity of the assignment operator is Right to Left
so first typeof y
will evaluate first which is string "undefined"
and assigned to z
and then y
would be assigned the value of z. The overall sequence will look like that:
var z;
z = 1;
var y;
z = typeof y;
y = z;
// NFE (Named Function Expression)
var foo = function bar() { return 12; };
typeof bar();
The output will be Reference Error
. To fix the bug we can try to rewrite the code a little bit:
Sample 1
var bar = function() { return 12; };
typeof bar();
or
Sample 2
function bar() { return 12; };
typeof bar();
The function definition can have only one reference variable as a function name, In sample 1 bar
is reference variable which is pointing to anonymous function
and in sample 2 we have function statement and bar
is the function name.
var foo = function bar() {
// foo is visible here
// bar is visible here
console.log(typeof bar()); // Works here :)
};
// foo is visible here
// bar is undefined here
var foo = function() {
// Some code
};
function bar () {
// Some code
};
The main difference is function foo
is defined at run-time
and is called function expression, whereas function bar
is defined at parse time and is called function statement. To understand in better, let's see below code :
// Run-Time function declaration
<script>
foo(); // Call foo function here, It will give an error
var foo = function() {
console.log("Hi I am inside Foo");
};
</script>