JavaScript Flashcards

1
Q

What are prototypes in JavaScript?

A

“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

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

Explain the difference between pass by value and pass by reference.

A

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

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

What is the drawback of creating a true private function in JS?

A

“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

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

Explain the difference between Function, Method and Constructor calls in JavaScript.

A

“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

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

Can you describe the main difference between .forEach() and .map() and why you would pick one versus the other?

A

“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

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

Explain the difference between function declaration vs. function expression.

A

“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 well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

How would you empty an array in JS?

A

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

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

What are the ways by which we can create objects in JS?

A

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 well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

How does one prevent a JS object from being modified?

A

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

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

Write a function that will test a given string as a literal and as an object.

A

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 well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

How would you merge two objects?

A
Use Object.assign() (ES6):
const merge = (obj1, obj2) => {
  return Object.assign(obj1, obj2);
};
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

How could you merge two objects without built-in method?

A
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
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

What is NaN? What is its type? How can you reliably test if a value is NaN?

A

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

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

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?

A

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 well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

How would you compare two objects in JavaScript?

A

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

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

How would you find an Object’s size?

A

Method 1:
Create a function that iterates over each property and keeps track of a count.

const bookAuthors = {
“Farmer Giles of Ham”: “J.R.R. Tolkien”,
“Out of the Silent Planet”: “C.S. Lewis”,
“The Place of the Lion”: “Charles Williams”,
“Poetic Diction”: “Owen Barfield”
};

const countProperties = (obj) => {
    let count = 0;
    for (let property in obj) {
        if (Object.prototype.hasOwnProperty.call(obj, property)) {
            count++;
        }
    }
return count; };

const bookCount = countProperties(bookAuthors);

// Outputs: 4
console.log(bookCount);

Method 2:
Create an array of Object properties (or keys) and get the length of that array.

const bookCount = Object.keys(bookAuthors).length;

// Outputs: 4
console.log(bookCount);

Source: A Drip of JavaScript

17
Q

What happens if you try to invoke a constructor function without the new keyword?

A

ES5 example:

function Color(r, g, b) {
  this.r = r;
  this.g = g;
  this.b = b;
}
// Safe invocation:
var red = new Color(255, 0, 0);
// Dangerous invocation:
var blue = Color(0, 0, 255);
In the safe invocation example, the this value in the constructor function is set to the new object being created. However, in the dangerous invocation example (i.e. invoking the constructor function like a normal function), the this value is the same this variable that any other function gets. Usually, this variable refers to the global object (or window in the browser).

Suppose we had a global variable r:

// global variable:
r = 'rainbows and unicorns'
function Color(r, g, b) {
  this.r = r;
  this.g = g;
  this.b = b;
}
// Dangerous invocation:
var blue = Color(0, 0, 255);

console.log(r); // output: 0

console.log(blue); // outputs: undefined
One way to prevent this from accidentally happening is to add a check to see if this is an instance of the object:

// global variable:
r = 'rainbows and unicorns'
function Color(r, g, b) {
  if (this instanceof Color) {
    this.r = r;
    this.g = g;
    this.b = b;
  } else {
    return new Color (r, g, b);
    // Alternatively, throw an error
    // throw new Error("`Color` invoked without `new`");
  }
}
// Dangerous invocation:
var blue = Color(0, 0, 255);

console. log(r); // output: ‘rainbows and unicorns’
console. log(blue); // outputs: { r: 0, g: 0, b: 255 }

Source: A Drip of JavaScript

18
Q

Explain the difference between a Boolean object and a Boolean primitive?

A

In JavaScript, there are constructors for each of the primitive data types, but the constructor functions do not create the same thing as the primitives.

// Boolean primitives
let primitiveTrue = true;
let primitiveFalse = false;

console. log(primitiveTrue); // outputs true
console. log(primitiveFalse); // outputs false

// Boolean objects
let constructorTrue = new Boolean(true);
let constructorFalse = new Boolean(false);

console. log(constructorTrue); // outputs [Boolean: true]
console. log(constructorFalse); // outputs [Boolean: false]

Booleans created with the Boolean constructor return objects, instead of primitives.

Using the Boolean constructor can be dangerous. When using an object in a context that expects a boolean value, the object will be coerced to true. The Boolean object is the type ‘object’, so it will also coerce to true, even if its internal value is false.

const truthyOrFalsey = (variable) => {
  if (variable) {
    console.log('this variable is a truthy value');
  } else {
    console.log('this variable is a falsey value');
  }
}

truthyOrFalsey(primitiveFalse); // outputs ‘this is a falsey value’
truthyOrFalsey(constructorFalse); // outputs ‘this is a truthy value’
A workaround for this is to use the valueOf() method to get the internal value of the Boolean object:

// Outputs: "The value of my false Boolean object is falsy!"
if (constructorFalse.valueOf()) {
    console.log("The value of my false Boolean object is truthy!");
} else {
    console.log("The value of my false Boolean object is falsy!");
}

Source: A Drip of JavaScript

19
Q

Is it possible to use Array methods on a string?

A

In JavaScript, strings are immutable. So methods like push(), pop(), shift() and splice() will not work on strings.

However, methods that treat strings as read-only will work on strings. For example:

const ontologist = “Anselm”;

const hasSomeA = [].some.call(ontologist, function(val) {
    return val === "A";
});

console.log(hasSomeA); // Outputs: true

const everyCharIsE = [].every.call(ontologist, function(val) {
    return val === "E";
});

console.log(everyCharIsE); // Outputs: false

const beforeM = [].filter.call(ontologist, function(val) {
    return val < "m";
});
console.log(beforeM); // Outputs: ["A", "e", "l"]
// note that filter returns an array, rather than a string.
// using `call` or `apply` doesn't change the function's logic,
// just the value it operates on.

Source: A Drip of JavaScript

20
Q

What methods could one use to determine if a string contains a substring?

A

(1) String.prototype.indexOf()

const isSubStr = (str, subStr) => {
  if (str.indexOf(subStr) >= 0) {
    console.log(`${subStr} is a substring of ${str}`);
  } else {
    console.log(`${subStr} is NOT a substring of ${str}`);
  }
}

isSubStr(‘Blue Whale’, ‘Blue’);
// “Blue is a substring of Blue Whale”
isSubStr(‘Blue Whale’, ‘Blute’);
// “Blute is NOT a substring of Blue Whale”

“While indexOf is often recommended as a simple way to test for the presence of a substring, that’s not really its purpose. Its job is to return the index at which a given substring is found. In the event that no match is found, it will return -1. That means that we can use it, but the clarity of the code suffers. Ideally, what we’re looking for is a method with a name that matches our intention (determining if x contains y), and returns a simple true or false.”

String.prototype.search() has the same behavior as indexOf(), with the exception of matching a regular expression rather than a string.

(2) RegExp.prototype.test()

const isSubStr = (str, subStr) => {
  let subStrRegExp = new RegExp(subStr)
  if (subStrRegExp.text(str)) {
    console.log(`${subStr} is a substring of ${str}`);
  } else {
    console.log(`${subStr} is NOT a substring of ${str}`);
  }
}

isSubStr(‘Blue Whale’, ‘Blue’); // “Blue is a substring of Blue Whale”
isSubStr(‘Blue Whale’, ‘Blute’); // “Blute is NOT a substring of Blue Whale”
This method is slightly better than String.prototype.indexOf() as it returns a boolean value and its method name communicates its intent more clearly. Unfortunately, we would run into problems if we try to match strings that include characters like ? or . because they have special meanings in regular expressions. In this case, we would have to deal with escaping them.

(3) String.prototype.includes() (formerly named String.prototype.contains())

const isSubStr = (str, subStr) => {
  if (str.includes(subStr)) {
    console.log(`${subStr} is a substring of ${str}`);
  } else {
    console.log(`${subStr} is NOT a substring of ${str}`);
  }
}

isSubStr(‘Blue Whale’, ‘Blue’); // “Blue is a substring of Blue Whale”
isSubStr(‘Blue Whale’, ‘Blute’); // “Blute is NOT a substring of Blue Whale”
This method returns a boolean value AND clearly conveys the intent of the code. Note that the includes() method is case sensitive.

Source: A Drip of JavaScript
Source: MDN web docs

21
Q

What is this in JavaScript?

A

“There’s no simple explanation for this; it is one of the most confusing concepts in JavaScript. A hand-wavey explanation is that the value of this depends on how the function is called. I have read many explanations on this online, and I found Arnav Aggrawal’s explanation to be the clearest. The following rules are applied:

(1) If the new keyword is used when calling the function, this inside the function is a brand new object.
(2) If apply, call, or bind are used to call/create a function, this inside the function is the object that is passed in as the argument.
(3) If a function is called as a method, such as obj.method() — this is the object that the function is a property of.
(4) If a function is invoked as a free function invocation, meaning it was invoked without any of the conditions present above, this is the global object. In a browser, it is the window object. If in strict mode (‘use strict’), this will be undefined instead of the global object.

If multiple of the above rules apply, the rule that is higher wins and will set the this value.

If the function is an ES2015 arrow function, it ignores all the rules above and receives the this value of its surrounding scope at the time it is created.”

The value of this is usually determined by a function’s execution context.

In the global scope, this refers to the global Object (or the window Object in the browser).

// in the browser
console.log(this); // returns Window {...}
Depending on how a function is called, the this inside a function can still refer to the global Object.
function myFunction() {
  return this;
}

myFunction(); // returns Window {…} in the browser
When this is used inside a declared object (or Object literal), this is set to the closest parent object the method is called on.

const breakfast = {
  name: 'Breakfast',
  age: 2,
  displayThis: function () {
    console.log(this);
  },
  markov: {
    name: 'Markov',
    age: 3,
    displayThis: function () {
      console.log(this);
    }
  }
}
breakfast.displayThis(); 
// => { name: 'Breakfast', age: 2, displayThis: function }
breakfast.markov.displayThis();
// => { name: 'Markov', age: 3, displayThis: function }

When creating an instance of an object using the new keyword, this is bound to that new object instance.

class Cat {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }

displayThis() {
console.log(this);
}
}

const breakfast = new Cat('Breakfast', 2);
const markov = new Cat('Markov', 3);
breakfast.displayThis(); // Cat { name: "Breakfast", age: 2 }
markov.displayThis(); // Cat { name: "Markov", age: 3 }

The value of this can be set explicitly with call(), apply() and bind().

function displayThis() {
  console.log(this);
}
// call the function in the browser
displayThis(); // => Window {...}
// declare an object
const obj = {
  name: 'some random object'
};
displayThis.call(obj); // => { name: "some random object" }
// the `this` value becomes the first parameter passed in the call() method.

// let’s look at another example:

// declare a function `add`
function add(b, c) {
  return this + b + c;
}
// call the function
add(2, 3); // => "[object Window]23"

let num = 10;

add.call(num, 2, 3); // => 15
// in this case, `this` refers to the variable `num`

Note: ES6 Arrow Functions do not bind this - instead, this is bound lexically (i.e. based on the original context).

Source: codeburst.io Source: MDN web docs Source: Sitepoint Source: JavaScript.isSexy

22
Q

What’s the difference between host objects and native objects?

A

Native objects are objects that are part of the JavaScript language defined by the ECMAScript specification, such as String, Math, RegExp, Object, Function, etc.

Host objects are provided by the runtime environment (browser or Node), such as window, XMLHTTPRequest, etc.

Source: Front End Interview Handbook

23
Q

What’s the difference between .call and .apply?

A

Both .call() and .apply() are used to invoke functions and the first parameter will be used as the value of this within the function. However, .call takes in a comma-separated arguments as the next arguments while .apply takes in an array of arguments as the next argument. An easy way to remember this is C for call and comma-separated and A for apply and array of arguments.

function add(b,c) {
  return this + b + c;
}

console. log(add.call(1, 2, 3)); // => 6
console. log(add.apply(1, [2, 3])); // => 6

// note: does not work if the function add was written with as a ES6 fat-arrow function

Source: Front End Interview Handbook

24
Q

What is AJAX?

A

Ajax (asynchronous JavaScript and XML) is a set of web development techniques using many web technologies on the client side to create asynchronous web applications. With Ajax, web applications can send data to and retrieve from a server asynchronously (in the background) without interfering with the display and behavior of the existing page. By decoupling the data interchange layer from the presentation layer, Ajax allows for web pages, and by extension web applications, to change content dynamically without the need to reload the entire page. In practice, modern implementations commonly substitute JSON for XML due to the advantages of being native to JavaScript.

The XMLHttpRequest API is frequently used for the asynchronous communication or these days, the fetch API.

Source: Front End Interview Handbook

Follow-up: What are the advantages and disadvantages of using Ajax?

Advantages

  • Better interactivity. New content from the server can be changed dynamically without the need to reload the entire page.
  • Reduce connections to the server since scripts and stylesheets only have to be requested once.
  • State can be maintained on a page. JavaScript variables and DOM state will persist because the main container page was not reloaded.
  • Basically most of the advantages of an SPA.

Disadvantages

  • Dynamic webpages are harder to bookmark.
  • Does not work if JavaScript has been disabled in the browser.
  • Some webcrawlers do not execute JavaScript and would not see content that has been loaded by JavaScript.
  • Basically most of the disadvantages of an SPA.

Source: Front End Interview Handbook

25
Q

What are the pros and cons of using Promises instead of callbacks?

A

Pros:

  • Avoid callback hell which can be unreadable.
  • Makes it easy to write sequential asynchronous code that is readable with .then().
  • Makes it easy to write parallel asynchronous code with Promise.all().

Cons:

  • Slightly more complex code (debatable).
  • In older browsers where ES2015 is not supported, you need to load a polyfill in order to use it.

Source: Front End Interview Handbook

26
Q

What are callbacks and promises?

A

A callback function, also known as a higher-order function, is a function that is passed to another function as a parameter, and can be called (or executed) inside the original function.

A promise is a proxy for a value not necessarily known at its creation time. With promises, rather than an asynchronous call accepting a callback, it instead returns a promise. The calling code can then wait until that promise is fulfilled before executing the next step. To do so, the promise has a method .then(), which accepts a function that will be invoked when the promise has been fulfilled. As an example, the following is the above code rewritten using promises:

function isUserTooYoung(id) {
    return openDatabase()
        .then(getCollection)
        .then(find.bind(null, {'id': id}))
        .then(function(user) {
            return user.age < cutoffAge;
        });
}
27
Q

What is REST? What does it mean to be RESTful?

A

REST or RESTful API design (Representational State Transfer) is designed to take advantage of existing protocols. While REST can be used over nearly any protocol, it usually takes advantage of HTTP when used for Web APIs. This means that developers do not need to install libraries or additional software in order to take advantage of a REST API design. It is notable for its incredible layer of flexibility. Since data is not tied to methods and resources, REST has the ability to handle multiple types of calls, return different data formats and even change structurally with the correct implementation of hypermedia.

This freedom and flexibility inherent in REST API design allow you to build an API that meets your needs while also meeting the needs of very diverse customers. Unlike SOAP, REST is not constrained to XML, but instead can return XML, JSON, YAML or any other format depending on what the client requests. And unlike RPC, users aren’t required to know procedure names or specific parameters in a specific order.

However, there are drawbacks to REST API design. You can lose the ability to maintain state in REST, such as within sessions, and it can be more difficult for newer developers to use.

There are 6 key constraints to think about when considering whether a RESTful API is the right type of API for your needs:

  • Client-Server: This constraint operates on the concept that the client and the server should be separate from each other and allowed to evolve individually.
  • Stateless: REST APIs are stateless, meaning that calls can be made independently of one another, and each call contains all of the data necessary to complete itself successfully.
  • Cache: Because a stateless API can increase request overhead by handling large loads of incoming and outbound calls, a REST API should be designed to encourage the storage of cacheable data.
  • Uniform Interface: The key to the decoupling client from server is having a uniform interface that allows independent evolution of the application without having the application’s services, or models and actions, tightly coupled to the API layer itself.
  • Layered System: REST APIs have different layers of their architecture working together to build a hierarchy that helps create a more scalable and modular application.
  • Code on Demand: Code on Demand allows for code or applets to be transmitted via the API for use within the application.
28
Q

What happens when you type in a URL in the browser and hit enter?

A

1) The browser goes to the DNS (Domain Name Server) and looks up the real address of the server that the website lives on.
2) The browser sends a HTTP request message to the server and asks the server to send a copy of the website to the client. The request and response messages are sent across the internet connection using TCP/IP (Transmission Control Protocol and Internet Protocol).
3) If the server approves the client’s request, the server sends the client a “200 OK” message to indicate that the request was successful and then starts sending the website’s files to the browser as data packets.
4) The browser assembles the data packets into a complete website and displays it to the user.

29
Q

What is HTTP?

A

HTTP stands for Hypertext Transfer Protocol and is an application protocol that defines a language for clients and servers to speak to each other.

30
Q

What is TCP/IP?

A

TCP/IP stands for “Transmission Control Protocol and Internet Protocol” and are communication protocols that define how data should travel across the web.

31
Q

What is DNS?

A

DNS stands for “Domain Name Servers” and are like an address book for website. When you type a web address into a browser, the browser looks at the DNS to find the web site’s real address before it can retrieve the website. The browser needs to tifnd out which server the website lives on, so it can send HTTP message to the right place.

Real web addresses are not memorable strings typed into the address bar of a browser (i.e. a URL). Instead, they are special numbers that look like this: 63.245.215.20. This is called an IP address and represents a unique location on the web.