JavaScript Flashcards
What are prototypes in JavaScript?
“Prototypes are the mechanism by which JavaScript objects inherit features from one another, and they work differently than inheritance mechanisms in classical object-oriented programming languages.”
“JavaScript is often described as a prototype-based language — each object has a prototype object, which acts as a template object that it inherits methods and properties from. An object’s prototype object may also have a prototype object, which it inherits methods and properties from, and so on. This is often referred to as a prototype chain, and explains why different objects have properties and methods defined on other objects available to them.
Well, to be exact, the properties and methods are defined on the prototype property on the Objects’ constructor functions, not the object instances themselves.”
“…a link is made between the object instance and its prototype (its __proto__ property, which is derived from the prototype property on the constructor), and the properties and methods are found by walking up the chain of prototypes.”
Source: MDN Docs
Explain the difference between pass by value and pass by reference.
Primitive type (null, undefined , boolean, number, string and ES6 symbol) are passed by value and objects are passed by reference. If you change a property of the passed object, the change will be affected. However, you assign a new object to the passed object, the changes will not be reflected.
Example:
var a = 2; // ‘a’ hold a copy of the value 2.
var b = a; // ‘b’ is always a copy of the value in ‘a’
b++;
console.log(a); // 2
console.log(b); // 3
var c = [1,2,3];
var d = c; // ‘d’ is a reference to the shared value
d.push( 4 ); // Mutates the referenced value (object)
console.log(c); // [1,2,3,4]
console.log(d); // [1,2,3,4]
/* Compound values are equal by reference */ var e = [1,2,3,4]; console.log(c === d); // true console.log(c === e); // false
Sources:
That JS Dude | Pass by value vs by reference
freecodecamp | The Definitive JavaScript Handbook for a developer interview
What is the drawback of creating a true private function in JS?
“One of the drawbacks of creating true private methods in JavaScript is that they are very memory-inefficient, as a new copy of the method would be created for each instance.”
var Employee = function (name, company, salary) {
this. name = name || ""; //Public attribute default value is null this. company = company || ""; //Public attribute default value is null this. salary = salary || 5000; //Public attribute default value is null
// Private method var increaseSalary = function () { this.salary = this.salary + 1000; };
// Public method this.displayIncreasedSalary = function() { increaseSalary(); console.log(this.salary); }; };
// Create Employee class object var emp1 = new Employee("John","Pluto",3000); // Create Employee class object var emp2 = new Employee("Merry","Pluto",2000); // Create Employee class object var emp3 = new Employee("Ren","Pluto",2500);
“Here each instance variable emp1, emp2, emp3 has its own copy of the increaseSalary private method.
So, as a recommendation, don’t use private methods unless it’s necessary.”
Source: CodeMentor | 21 Essential JavaScript Interview Questions
Explain the difference between Function, Method and Constructor calls in JavaScript.
“In JavaScript, these are just three different usage patterns of one single construct.
1) Functions : The simplest usages of function call:
function helloWorld(name) { return "hello world, " + name; }
helloWorld(“JS Geeks”); // “hello world JS Geeks”
2) Methods in JavaScript are nothing more than object properties that reference to a function.
var obj = { helloWorld : function() { return "hello world, " + this.name; }, name: 'John Carter' }
obj.helloWorld(); // // “hello world John Carter”
Notice how helloWorld refer to this properties of obj. Here it’s clear or you might have already understood that this gets bound to obj. But the interesting point that we can copy a reference to the same function helloWorld in another object and get a difference answer. Let see:
var obj2 = { helloWorld : obj.helloWorld, name: 'John Doe' } obj2.helloWorld(); // "hello world John Doe"
You might be wondering what exactly happens in a method call here. Here we call the expression itself determine the binding of this this, The expression obj2.helloWorld() looks up the helloWorld property of obj and calls it with receiver object obj2.
3) The third use of functions is as constructors. Like function and method, constructors are defined with function.
function Employee(name, age) { this.name = name; this.age = age; }
var emp1 = new Employee(‘John Doe’, 28);
emp1. name; // “John Doe”
emp1. age; // 28
Unlike function calls and method calls, a constructor call new Employee(‘John Doe’, 28) create a brand new object and passes it as the value of this, and implicitly returns the new object as its result.
The primary role of the constructor function is to initialize the object.”
Source: 123 Essential JavaScript Interview Questions
Can you describe the main difference between .forEach() and .map() and why you would pick one versus the other?
“forEach() — executes a provided function once for each array element.
map() — creates a new array with the results of calling a provided function on every element in the calling array.””
“The forEach() method doesn’t actually return anything (undefined). It simply mutates the current array by calling a provided function on each element in your array. Meanwhile, the map() method will also call a provided function on every element in the array. The difference is that map() utilizes return values and actually returns a new Array of the same size.”
- forEach() is also slower than map()
- map() may be preferable for functional programming because map() does not mutate the original array.
- “forEach() may be preferable when you’re not trying to change the data in your array, but instead want to just do something with it — like saving it to a database or logging it out”
- “map() might be preferable when changing or altering data. Not only is it faster but it returns a new Array. This means we can do cool things like chaining on other methods ( map(), filter(), reduce(), etc.)”
TL;DR:
“Just about anything you can do with forEach() you can do with map(), and vise versa.
map() allocates memory and stores return values. forEach() throws away return values and always returns undefined.
forEach() will allow a callback function to mutate the current array. map() will instead return a new array”.
Source: codeburst.io
Explain the difference between function declaration vs. function expression.
“Function declarations begin with the ‘function’ keyword and must be named. We can pass values in the form of arguments and also return values. If a value is not returned, then the function will return undefined.”
function helloWorld() { return "hello world"; }
Function expressions
var helloWorld = function() { return "hello world"; }
“Although function declarations and function expressions are similar and often interchangeable, there is an important distinction:
Function Declarations are hoisted or pulled to the top of the function making them available regardless of position. So, we can call a function and then declare it further down and still access the function.
This may seem confusing since javascript typically interprets code line by line, from top to bottom. Despite this, function and also variable declarations are hoisted by the javascript interpreter while function and variables expressions are not.”
Example:
Function Declaration:
function foo() { bar(); function bar() { console.log("bar"); } }
foo(); // “bar”
Function Expression:
function foo() { bar(); var bar = function() { console.log("bar"); } }
foo(); // returns “TypeError: bar is not a function”
Source: learnsteady
How would you empty an array in JS?
Method 1:
Reassign the array variable to an empty array. Only works for var and let variables):
var array = [1,2,3]; array = [];
Recommended only if you don’t have references to the original array anywhere else. For example:
let array = [‘a’, ‘b’, ‘c’, ‘d’, ‘e’, ‘f’]; // Creates array
let anotherArray = array; // References array by another variable
array = []; // Empties the array
console.log(anotherArray); // Outputs [‘a’, ‘b’, ‘c’, ‘d’, ‘e’, ‘f’]
Method 2:
Set array length to 0.
array.length = 0;
Useful for updating all the reference variables that point to the original array. For example:
const array = ['a', 'b', 'c', 'd', 'e', 'f']; // Creates array const anotherArray = array; // References array by another variable array.length = 0; // Empties the array by setting length to 0 console.log(anotherArray); // Outputs []
Method 3:
Splice the array starting at index 0 to the length of the array
arrayList.splice(0, arrayList.length). Also updates the reference variables that point to the original array:
const array2 = [‘a’, ‘b’, ‘c’, ‘d’, ‘e’, ‘f’]; // Creates array
const anotherArray2 = array; // References array by another variable
array2.splice(0, array2.length); // Empties the array by setting length to 0
console.log(anotherArray2); // Outputs []
Method 4:
Use a while loop and Array.prototype.pop(). (Not recommended)
while (array.length) {
arrayList.pop();
}
Source: 123 Essential JS Interview Questions
What are the ways by which we can create objects in JS?
Method 1: Function Based
Useful for creating several similar objects.
class Cat(name, breed, color, age) { constructor() { this.name = name; this.breed = breed; this.color = color; this.age = age; } }
// Creates multiple object which have similar property but different value assigned to object property.
const breakfast = new Cat('Breakfast', 'Persian', 'white', 3); const markov = new Cat('Markov', 'Russian Blue', 'grey', 4); const muffin = new Cat('Muffin', 'Bombay', 'black', 2);
Method 2: Object Literal
Best way to create an object and is used frequently.
const breakfast = { name: 'Breakfast', breed: 'Persian', color: 'white', age: 3, getName: function(){ return this.name; } }
Method 3: Using JS new keyword
const breakfast = new Object(); breakfast.name = 'Breakfast'; breakfast.getName = function(){ return this.name; }
Note: best practice is to use the object literal method over the new keyword method.
Source: 123 Essential JS Interview Questions
How does one prevent a JS object from being modified?
There are three levels of preventing object modification:
1) Prevent extensions: No new properties or methods can be added to the object, but existing properties and methods can be changed.
const breakfast = { name: 'Breakfast' };
// lock the object Object.preventExtensions(breakfast);
// Try to change the object property name:
breakfast. name = ‘Markov’;
console. log(breakfast.name); // => ‘Markov’
// Try to add a new object property: breakfast.age = 3; // fails silently unless in strict mode
2) Seal: Performs the same functionality as prevent extension but also prevents existing properties and methods from being deleted.
const breakfast = { name: 'Breakfast' };
// Seal the object: Object.seal(breakfast);
console. log(Object.isExtensible(breakfast)); // => false
console. log(Object.isSealed(breakfast)); // => true
delete breakfast.name; // fails silently unless in strict mode
breakfast. age = 3; // fails silently unless in strict mode
3) Freeze: Same properties as seal, but also prevent existing properties and methods from being modified (i.e. all properties and method are read-only).
const breakfast = { name: 'Breakfast' };
// Freeze the object: Object.freeze(breakfast);
console. log(Object.isExtensible(breakfast)); // => false
console. log(Object.isSealed(breakfast)); // => false
console. log(Object.isFrozen(breakfast)); // => true
breakfast.name = ‘Markov’; // fails silently unless in strict mode
breakfast.age = 3; // fails silently unless in strict mode
delete breakfast.name; // fails silently unless in strict mode
Note: It is recommended to use strict mode if you decided to prevent modification, seal or freeze an object to catch any errors.
Source: 123 Essential JS Interview Questions
Write a function that will test a given string as a literal and as an object.
There are two ways to create a string: Literal and Function-based.
let literalStr = "literal string"; let objectStr = new String("object string");
In the test function, test the literal string using the typeof operator and test the String object using the instanceof operator:
const isString = (str) => { return typeof(str) === 'string' || str instanceof String; };
// tests
let literalStr = "literal string"; let objectStr = new String("object string"); isString(literalStr); // => true isString(objectStr); // => true Source: 123 Essential JS Interview Questions
How would you merge two objects?
Use Object.assign() (ES6): const merge = (obj1, obj2) => { return Object.assign(obj1, obj2); };
How could you merge two objects without built-in method?
const merge = (obj1, obj2) => { // both params must be objects if (typeof obj1 === 'object' && typeof obj2 === 'object') { for (let prop in obj2) { // only merge if obj2's property ('prop') is its own && not inherited if (obj2.hasOwnProperty(prop)) { obj1[prop] = obj2[prop]; } } return obj1; } else { throw 'merge will only work with two objects'; } };
let obj1 = { name: 'Julie'}; let obj2 = { age: 27 };
// Tests: // console.log('Object.assign method', Object.assign(obj1, obj2)); // console.log('merge function', merge(obj1, obj2)); Source: 123 Essential JS Interview Questions
What is NaN? What is its type? How can you reliably test if a value is NaN?
The NaN property represents a value that is “not a number”. This special value results from an operation that could not be performed either because one of the operands was non-numeric (e.g., “abc” / 4), or because the result of the operation is non-numeric (e.g., an attempt to divide by zero).
Although NaN means “not a number”, its type is, believe it or not, Number:
console.log(typeof NaN === “number”); // logs “true”
Additionally, NaN compared to anything – even itself! – is false:
console.log(NaN === NaN); // logs “false”
Testing if a value is NaN:
- Use isNaN() - somewhat reliable
- Special cases in which isNaN will return a false positive: empty string and boolean
- isNaN will type coerce the value passed in to type number and then check to see if that coerced value is “not a number”. An empty string/boolean will type coerce to numeric values, zero or one, hence the false positive.
Use value !== value. If a value is actually NaN, then it would not be equal to itself (NaN !== NaN => true). This approach is useful because it works across browsers.
- Use ES6’s Number.isNaN(), which is more robust than the global isNaN (mentioned above). May not work across all browsers.
Source: 37 Essential JavaScript Interview Questions Source: MDN Web Docs - isNaN() Source: MDN Web Docs - Number.isNaN() Source: The Problem with Testing for NaN in JavaScript - A Drip of JavaScript
Can one use a for…in loop to iterate over an array? Why is it recommended not to use the for…in loop for array iteration?
The for…in loop can be used to iterate over an array.
const tMinus = [ "Two", "One", "Blast off!" ];
let countdown = “”;
for (let step in tMinus) {
countdown += tMinus[step] + “\n”;
}
console.log(countdown); // => "Two // One // Blast Off! // "
However, there are three problems with using the for…in loop on arrays.
The for…in also iterates over an object’s prototype properties if those properties are enumerable.
Array.prototype.voice = “James Earl Jones”;
const tMinus = [ "Two", "One", "Blast off!" ];
let countdown = “”;
for (let step in tMinus) {
countdown += tMinus[step] + “\n”;
}
console.log(countdown); // => "Two // One // Blast Off! // James Earl Jones // " This can be solved by using hasOwnProperty to exclude prototype properties.
Array.prototype.voice = “James Earl Jones”;
const tMinus = [ "Two", "One", "Blast off!" ];
let countdown = “”;
for (let step in tMinus) { if (tMinus.hasOwnProperty(step)) { countdown += tMinus[step] + "\n"; } }
console.log(countdown); // => "Two // One // Blast Off! // "
for…in loops may iterate over an object’s values in an arbitrary order. That’s not really a problem for an ordinary object whose values are inherently unordered anyway. But you probably don’t want your JavaScript engine handing back array values in a random order, because you could get unexpected results like this:
console.log(countdown); // => "Blast Off! // One // Two // "
It is possible to store additional properties on an array and for...in iterates over all enumerable properties, not just the array's elements. const tMinus = [ "Two", "One", "Blast off!" ];
tMinus.announcer = “Morgan Freeman”;
let countdown = “”;
for (let step in tMinus) { if (tMinus.hasOwnProperty(step)) { countdown += tMinus[step] + "\n"; } }
console.log(countdown); // => "Two // One // Blast Off! // Morgan Freeman // " Because of these problems, it is best to use a simple for loop or built-in array iterators like forEach() and map().
Source: A Drip of JavaScript
How would you compare two objects in JavaScript?
Since objects are compared by their reference (or space in memory), we cannot do a direct equality comparison with the === operator.
Instead, we can check for two things: 1) whether both objects have the same number of properties, and 2) whether both objects have the same values for each property. Our isEqual() function might look like this:
const isEqual = (objA, objB) => { // check whether both objects have the same number of properties, or keys if (Object.keys(objA).length !== Object.keys(objB).length) return false;
// check whether both objects have the same values for each property for (let prop in objA) { if (objA[prop] !== objB[prop]) { return false; } } return true; }; However, there are a few limitations:
- If one of the property values is another object.
- If one of the property values is NaN (because NaN never equates to itself)
- If one object has a property with value undefined, while another object doesn’t have the property (which thus evaluates as undefined)
For the first limitation, one could add a conditional in the for…in loop to check if the values in both objects are objects and then recursively call isEqual() on those object values.
if (typeof objA[prop] === 'object' && typeof objB[prop] === 'object') { return isEqual(objA[prop], objB[prop]); }
For a robust method of checking objects’ “value equality” it is better to rely on a well-tested library that covers the various edge cases. Both Underscore and Lo-Dash have implementations named _.isEqual which handle deep object comparisons well.
Source: thatjsdude Source: A Drip of JavaScript