Categories
JavaScript Interview Questions

JavaScript Interview Questions — Functions and Objects

Why Does foo.bar.baz Property Throw an Error?

If the bar property or bar.baz property is undefined or null or it doesn’t exist, then we will get an error indicating that either one is undefined or null .

Also, the object’s prototype also doesn’t have the property or is undefined or null .

We should check that these properties exist and isn’t null or undefined so that the code doesn’t throw an error.

What is the prototype of an object?

The prototype of an object is the template for an object. It’s used as a fallback of properties and methods if they don’t exist on the object itself.

Objects inherit properties and methods from their prototype in JavaScript.

For example, the following object:

const obj = {};
console.log(obj.__proto__)

has a prototype as defined by the __proto__ property. In the console.log output, we should see various properties and methods logged, like toString , toLocaleString , etc.

The JavaScript interpreter will search for properties and methods with the identifier we indicated into the code by searching the object, and up the prototype chain, until it exhausted all the prototypes in the prototype chain.

All objects ultimately inherit from Object.prototype .

What is an IIFE and what do we use it for?

IIFE stands for Immediately Invoked Function Expression. It’s a function that we defined on the fly and then run it immediately.

We do this by wrapping the function expression inside parentheses and then add the parentheses in the end to call that function.

An IIFE looks like:

(function () {

}());

or:

(() =>{

})();

The function can also be named if we write the following traditional function:

(function foo() {

})();

We can also return something from the function and assign it immediately:

const foo = (()=> {
 return 'foo';
})();

Then the value of foo is 'foo' .

We can also pass in arguments like any other function:

const foo = ((a, b)=> {
 return a + b;
})(1,2);

Then foo is 3.

IIFEs are useful for hiding items from the outside before we have modules. Also, it also lets us avoid polluting the global namespace before we have modules.

What is the Function.prototype.apply method?

The apply method lets us call a function with a different value of this and pass in values into the function arguments as an array.

For example, we can write:

function greet(greeting){
 return `${greeting} ${this.name}`;
}

const person = {
 name: 'Jane'
}

console.log(greet.apply(person, ['Hello']));

In the code above, we created a greet function, which takes a greeting argument.

Then we defined a person object with a name property.

We then call greet with the apply method by passing in person as the first argument, which is the value of this that we want in the function. The second argument is an array which we pass into greet as arguments.

In the case, we passed in 'Hello' of as the value of the greeting parameter.

The result of the console.log is Hello Jane .

apply doesn’t work with arrow functions since it doesn’t have its own this value.

What is the Function.prototype.call method?

The call method of a function is very similar to apply , except that we pass in a comma-separated list of arguments to call the function with arguments instead of passing in an array to pass in arguments to the function that call is called on.

For example, we can write the following code:

function greet(greeting){
 return `${greeting} ${this.name}`;
}

const person = {
 name: 'Jane'
}

console.log(greet.call(person, 'Hello'));

As we can see, the only difference between call and apply is whatever is after the first argument.

call doesn’t work with arrow functions since it doesn’t have its own this value.

What is Function.prototype.bind method?

The bind method lets us change the this value inside a function like call and apply .

Like call and apply , we pass in the object that we want to be the value of this inside the function as follows:

function greet(){
 return `${this.name}`;
}

const person = {
 name: 'Jane'
}

const greetPerson = greet.bind(person);
console.log(greetPerson());

bind doesn’t work with arrow functions since it doesn’t have its own this value.

In the code above, we passed person into bind , so this.name would be 'Jane' . We can assign the function returned by bind to a new variable or constant. Then we can call it as we did as we have above.

Therefore, console.log would give us ‘Jane’.

Conclusion

JavaScript programs will throw errors if we try to access a property when a parent’s property doesn’t exist.

IIFEs are functions that are created on the fly and then called right after it’s defined.

The call and apply methods let us call functions with a different this value and arguments that we pass in. bind lets us change the this value inside the function. Then we can call the returned function that has a different this value and then call it.

Categories
JavaScript Interview Questions

JavaScript Interview Questions — Functions and Objects

To get a job as a front end developer, we need to nail the coding interview.

In this article, we’ll look at some functions and object questions.

What are Arrow Functions?

Arrow functions are a new way to define functions in JavaScript. It’s available since ES2015.

It takes away the confusion with this since it doesn’t bind to this and so they can’t be used as constructor functions.

They also can’t be hoisted, so they can only be used after they’re defined.

Also, they don’t bind to the arguments object, so we can’t get the arguments that are passed into arrow functions with it like in function declarations.

To get arguments from an arrow function, we use the rest syntax as follows:

const getArgs = (...rest) => rest

For example, we can define an arrow function as follows:

const currentDate = () => new Date();

In the code above, we defined the arrow function with => and returns new Date() to return the current date.

If we want to return something in a multi-line arrow function, we have to write return explicitly like any other function.

For example, we can write:

const currentDate = () => {
  return new Date();
}

to return new Date() explicitly in a multi-line arrow function.

We can pass in parameters like any other function as follows:

const identity = (obj) => {
  return obj;
}

What are Classes?

In JavaScript, classes are syntactic sugar for constructor functions. It’s used to create instances of a class but hides the prototype manipulations from our view.

Underneath, it still uses the prototype inheritance model that it has always been using.

For example, if we have the following chain of classes:

class Person {
  constructor(firstName, lastName) {
    this.lastName = lastName;
    this.firstName = firstName;
  }

  fullName() {
    return `${this.firstName} ${this.lastName}`;
  }
}

class Employee extends Person {
  constructor(firstName, lastName, title) {
    super(firstName, lastName);
    this.title = title;
  }

  getTitle() {
    return this.title;
  }
}

In the code above we have the Person class with a constructor and a method to get the full name.

Then we have the Employee class that extends the Person class as we indicated with the extends keyword.

In the constructor, we call the Person class’s constructor and also set the title field, which is exclusive to Employee.

We also added a getTitle method.

The JavaScript interpreter will give us an error if we forgot to call the super function.

This is the same as the following code, written with constructor functions:

function Person(firstName, lastName) {
  this.lastName = lastName;
  this.firstName = firstName;
}

Person.prototype.fullName = function() {
  return `${this.firstName} ${this.lastName}`;
}

function Employee(firstName, lastName, title) {
  Person.call(this, firstName, lastName);
  this.title = title;
}

Employee.prototype = Object.create(Person.prototype);

Employee.prototype.getTitle = function() {
  return this.title;
}

The code above is the same as what we had with the classes, except that we get no errors if Person.call or Object.create was missing.

We also have to add things to the prototype of each constructor function outside the function.

Even though we don’t use the constructor function syntax, we have to know that the class syntax is just syntactic sugar for constructor functions.

What is Object Destructuring?

Object destructuring is a clean way to assign array entries or object properties into their own variables.

For example, we can use it to decompose array entries to individual variables as follows:

const [one, two] = [1, 2];

Then one is 1 and two is 2.

The code above is the same as:

const arr = [1, 2];
const one = arr[0];
const two = arr[1];

Likewise, we can do the same with an object as follows:

const {
  one,
  two
} = {
  one: 1,
  two: 2
}

Then the one property’s value is assigned to one , and two ‘s value is assigned to two .

The code above is the same as:

const obj = {
  one: 1,
  two: 2
}
const one = obj.one;
const two = obj.two;

As we can see, object and array destructuring is much cleaner than the old way.

We can also set variables to default values by writing:

const [one, two, three = 3] = [1, 2];

Then since three has not array entry assigned to it, three has a value of 3.

Conclusion

Arrow functions are useful for creating functions that aren’t constructor functions. They don’t bind to this. Also, it’s shorter since we don’t have to write return to return something if it’s one line.

Classes in JavaScript are syntactic sugar for constructor functions. It lets us do inheritance and create instance methods easier since we don’t have to manipulate prototypes directly and the JavaScript interpreter will give us errors if we missed anything.

Object and array destructuring let us assign object or array entries into variables in a clean way.

Categories
JavaScript Interview Questions

JavaScript Interview Questions — Arrays

To get a job as a front end developer, we need to nail the coding interview.

In this article, we’ll look at some JavaScript array questions.

Implement the Array.prototype.map method by hand.

The Array.prototype.map method maps each array entry to new entry by calling a callback function to do the mapping.

It returns a new array with the mapped values.

We can implement it as follows:

const map = (arr, callback) => {
  if (!Array.isArray(arr)) {
    return [];
  }
  const newArr = [];
  for (let i = 0, len = arr.length; i < len; i++) {
    newArr.push(callback(arr[i], i, arr));
  }
  return newArr;
}

First, we check if arr is an array, we return an empty array if it’s not.

In the code above, we have the map method that loops through each array entry and calls a callback with the array entry, index, and the original array passed in. Each entry is pushed to newArr array.

Then it returns the newArr array, which has the mapped entries.

Implement the Array.prototype.filter method by hand.

The Array.prototype.filter method returns a new array that takes the elements from the original array that meets the predicate in a callback, push those entries into a new array, then returns it.

We can implement that as follows:

const filter = (arr, callback) => {
  if (!Array.isArray(arr)) {
    return [];
  }
  const newArr = [];
  for (let i = 0, len = arr.length; i < len; i++) {
    if (callback(arr[i], i, arr)) {
      newArr.push(arr[i]);
    }
  }
  return newArr;
}

In the code above, we first check if arr is an array. We return an empty array if it’s not.

Then we loop through arr and then use an if block to check if the callback call returns true , then we push those entries to newArr and returns it.

Implement the Array.prototype.reduce method by hand.

The Array.prototype.reduce method combines an array’s entry into one by calling a callback repeatedly to combine the array entries into one value.

For example, we can write the following:

const reduce = (arr, reduceCallback, initialValue) => {
  if (!Array.isArray(arr)) {
    return;
  }
  let val = initialValue || 0;
  for (let i = 0, len = arr.length; i < len; i++) {
     val = reduceCallback(val, arr[i]);
  }
  return val;
}

We first check if arr is an array, then we return if it’s not an array.

Then we set val to initialValue if it exists or 0.

Next, we loop through the array and then use the reduceCallback to combine val and arr[i] and returns the new value and assign it to val .

Once the loop is done, we return val .

What’s the arguments object?

The arguments object is an array-like object that returns the arguments that are passed into a traditional function.

It doesn’t work with arrow functions.

It’s an array-like object because its entries can be accessed by indexes and it has a length property. arguments has no array methods.

Also, it can be looped through by the for...of loop and be converted to an array with the spread operator.

For example, if we write:

function logArgs() {
  console.log(arguments)
}

logArgs(1, 2, 3, 4, 5);

Then we see something like:

Arguments(5) [1, 2, 3, 4, 5, callee: ƒ, Symbol(Symbol.iterator): ƒ]

from the console.log .

We can see the entries and the Symbol.iterator method, so we know it’s an iterable object.

We can convert it to an array using the spread operator as follows:

function logArgs() {
  console.log([...arguments])
}

logArgs(1, 2, 3, 4, 5);

Then the console.log gives [1, 2, 3, 4, 5] , which is a regular array.

For arrow functions, we use the rest operator to get all the arguments as follows:

const logArgs = (...args) => {
  console.log(args)
}

logArgs(1, 2, 3, 4, 5);

We see [1, 2, 3, 4, 5] logged.

How do you add an element at the beginning of an array?

We can use the Array.prototype.unshift method to add an element to the beginning of an array.

For example, we can write:

const arr = [2, 3, 4];
arr.unshift(1);

Then arr is [1, 2, 3, 4] .

The spread operator also works for this:

let arr = [2, 3, 4];
arr = [1, ...arr];

Note that we changed const to let since we assigned to a new value.

How do you add an element at the end of an array?

We can use the push method to do add an entry to the end of an array.

For example, we can write:

const arr = [2, 3, 4];
arr.push(1);

Then arr is [2, 3, 4, 1] .

The spread operator also works for this:

let arr = [2, 3, 4];
arr = [...arr, 1];

Note that we changed const to let since we assigned to a new value.

Conclusion

We learn more about JavaScript arrays by implementing the array methods from scratch and practice doing common operations with them.

Categories
JavaScript Interview Questions

JavaScript Interview Questions — Data Types

To get a job as a front end developer, we need to nail the coding interview.

In this article, we’ll look at how some data type questions, including some trick questions that are often asked in interviews.

What are the falsy values in JavaScript?

In JavaScript, falsy values are the following

  • ''
  • 0
  • null
  • undefined
  • false
  • NaN

They become false when they’re converted to a boolean value.

How to check if a value is falsy?

Use the !! operator or Boolean function to check if they’re falsy.

If a value is falsy, then both will return false.

For example:

!!0

will return false.

Boolean(0)

will also return false.

What are truthy values?

Truthy values are any other than those falsy values listed above.

What are Wrapper Objects?

Wrapper objects are objects that are created from constructors that return primitive values but have the type 'object' if it’s a number or a string. Symbols and BigInt have their own types.

In JavaScript, there’s the Number, String constructors, and Symbol, and BigInt factory functions.

Primitive values are temporarily converted to wrapper objects to call methods.

For example, we can write:

'foo'.toUpperCase()

Then we get 'FOO'. It works by converting the 'foo' literal to an object and then call the toUpperCase() method on it.

We can also create wrapper objects for numbers and BigInt as follows:

new Number(1)
BigInt(1)

Using the Number or String constructor directly isn’t too useful, so we should avoid it. They give us the type of object but has the same content as their primitive counterparts.

If we did create Number and String wrapper objects with the new operator as follows:

const numObj = new Number(1);
const strObj = new String('foo');

We can return the primitive value version of those wrapper objects by using the valueOf method as follows:

numObj.valueOf();
strObj.valueOf();

What is the difference between Implicit and Explicit Coercion?

Implicit coercion means that the JavaScript interpreter converts a piece of data from one type to another without explicitly calling a method.

For example, the following expression are implicitly converted to a string:

console.log(1 + '2');

Then we get:

'12'

returned because 1 is converted to '1' implicitly.

Another example would be:

true + false

We get 1 returned because true is converted to 1 and false is converted to 0 and they’re added together.

The following example:

3 * '2'

returns 6 because '2' is converted to 2 and then they’re multiplied together.

The full list of JavaScript coercion rules are here.

Explicit conversion is done by calling a method or using an operator to convert a type.

We can see the coercion done in the code.

For example:

+'1' + +'2'

gets us 3 since we have '1' and '2' are both converted to numbers by the unary + operator.

We can also do the same things with functions. For example, we can use the parseInt function instead of using the unary + operator.

We can rewrite the expression above to:

parseInt('1') + parseInt('2')

Then we get the same result.

What Does 0 || 1 Return?

Since 0 is falsy, it’ll trigger the second operand to run, which gives us 1. Therefore, it should return 1.

What Does 0 && 1 Return?

Since 0 is falsy, it’ll stop running since we have short-circuited evaluation. Therefore, we get 0 returned.

What Does false == ‘0’ Return?

false is falsy and '0' is converted to 0, which is falsy, so they are the same in terms of the ==’s comparison criteria. Therefore, we should get true returned.

What Does 4 < 5 < 6 Return?

In JavaScript, comparisons are done from left to right. So first 4 < 5 will be evaluated, which gives us true . Then true < 6 is evaluated, which is converted to 1 < 6 which is also true .

Therefore, we get true returned.

What Does 6 > 5 > 4 Return?

In JavaScript, comparisons are done from left to right. So 6 > 5 will be evaluated first. This gives us true . Then true > 4 is evaluated, which is converted to 1 > 4 , which is false .

Therefore, the expression returns false .

What Does typeof undefined == typeof null Return?

typeof undefined returns 'undefined' and typeof null returns 'object' .

Since 'undefined' does equal 'object' , the expression should be false .

What Does typeof typeof 10 Return?

JavaScript evaluates typeof typeof 10 as typeof (typeof 10) . Therefore, this returns typeof 'number' , which returns 'string' since 'number' is a string.

Categories
JavaScript Interview Questions

JavaScript Interview Questions — Functions and Scope

To get a job as a front end developer, we need to nail the coding interview.

In this article, we’ll look at some basic functions and scope questions.

What is Hoisting?

Hoisting means that a variable or function is moved to the top of their scope of where we defined the variable or function.

JavaScripts moves function declarations to the top of their scope of we can reference them later and gets all variable declarations and give them the value of undefined .

During execution, the variables that were hoisted are assigned a value or runs functions.

Only function declarations and variables declared with the var keyword are hoisted.

Variables declared with let and const constants aren’t hoisted. Also, arrow functions and function expressions aren’t hoisted.

For example, the following code has a function that’s hoisted:

foo();

function foo(){
 console.log('foo')
}

foo is hoisted, so it can be called before it’s defined since it’s a function declaration.

The following variable declaration is hoisted:

console.log(x);
var x = 1;
console.log(x);

The first console.log outputs undefined since var x is hoisted.

Then when var x = 1 runs, x is set to 1. Then we get 1 logged in the second console.log since x has its value set before it.

Anything else isn’t hoisted.

What is Scope?

JavaScript’s scope is the area where we have valid access to a variable or function.

There’re 3 kinds of scopes in JavaScript — global, function, and block scope.

Variables and functions that have global scope are accessible everywhere in the script or module file.

For example, we can declare a variable with global scope as follows:

var global = 'global';

const foo = () => {
  console.log(global);
  const bar = () => {
    console.log(global);
  }
  bar();
}
foo();

Since we declared a variable with var on top of the code, it’s accessible everywhere. So both console.log s will output 'global' .

Function scoped variables are only available inside a function.

We can define a function scoped variable as follows:

const foo = () => {
  var fooString = 'foo';
  console.log(fooString);
  const bar = () => {
    console.log(fooString);
  }
  bar();
}
foo();

console.log(fooString);

In the code above, we have the function scoped variable fooString . It’s also declared with var and it’s available inside both the foo function and the nested bar function.

Therefore, we’ll get ‘foo’ logged with the 2 console.log statements inside the foo function.

The console.log at the bottom gives us an error because function scoped variables aren’t available outside a function.

Block scoped variables are only available inside a block. That is, inside an if block, function block, loop, or an explicitly defined block. Anything delimited by curly braces is a block.

They’re defined either with let or const depending if it’s variable or constant.

For instance, if we write:

if (true) {
  let x = 1;
  console.log(x);
}

console.log(x);

Then x is only available inside the if block. The console.log at the bottom gives us an x is not defined error.

Likewise, if we have had a loop:

for (let i = 0; i <= 1; i++) {
  let x = 1;
  console.log(x);
}

console.log(x);

Then x is only available inside the loop. The console.log at the bottom gives us an x is not defined error.

We can also define a block explicitly just to isolate variables from the outside:

{
  let x = 1;
  console.log(x);
}

console.log(x);

x will then only be available inside the curly braces. The bottom console.log will give us an error.

The scope determines how far the JavaScript will go to look for a variable. If it’s doesn’t exist in the current scope then it’ll look in the outer scope.

If it finds it in the outer scope and it’s declared in a way that we can access the variable then it’ll pick up that value.

Otherwise, if it’s not found, then we get an error.

What are Closures?

Closures are functions that remember the variables and parameters on its current scope and all the way up to the global scope.

In JavaScript, when an inner function has made available to any scope outside the outer function.

We can use it to expose private functions or data in a restricted way.

For example, we can write the following function that is a closure:

const foo = (() => {
  let x = 'Joe';
  const privateFn = () => {
    alert(`hello ${x}`);
  }

  return {
    publicFn() {
      privateFn();
    }
  }
})();

foo.publicFn();

In the code above, we have an (Immediately Invoked Function Expression) IIFE that runs a function that returns an object with a publicFn property, which is set to a function that calls privateFn , which is hidden from the outside.

Also, privateFn is called with x declared inside the function.

Then we call publicFn after assigning the returned object to foo .

What the code achieves is that we hid the private items within a closure, while exposing what we want to expose to the outside.

As we can see, the closure lets us hold items that’s resides in a scope not available to the outside while we can expose what we can use outside the closure.

One major use of closures is to keep some entities private while exposing necessary functionality to the outside.

Conclusion

Hoisting is the pulling of functions and variables to the top of the code during compilation.

Function declarations are hoisted fully, and variables declared with var has everything before the value assignment hoisted.

The scope is where a piece of code has valid access to a variable or constant.

Closures are a way to return inner functions with some of the entities of the outer function included. It’s useful for keeping some things private while exposing some functionality.