Skip to content

Instantly share code, notes, and snippets.

@ravid7000
Last active January 7, 2020 12:06
Show Gist options
  • Save ravid7000/663c6160313ddfa4b5c07dd84b1298ec to your computer and use it in GitHub Desktop.
Save ravid7000/663c6160313ddfa4b5c07dd84b1298ec to your computer and use it in GitHub Desktop.
Popular JavaScript Interview Questions.

Popular JavaScript Interview Questions.

Question #1. What will be the output of following code?

Note: A closure is basically when an inner function has access to variables outside of its scope. Closures can be used for things like implementing privacy and creating function factories.

  const arr = [10, 12, 15, 21];
  for (var i = 0; i < arr.length; i++) {
    setTimeout(function() {
      console.log('Index: ' + i + ', element: ' + arr[i]);
    }, 3000);
  }

Explaination:

The reason for this is because the setTimeout function creates a function (the closure) that has access to its outer scope, which is the loop that contains the index i. After 3 seconds go by, the function is executed and it prints out the value of i, which at the end of the loop is at 4 because it cycles through 0, 1, 2, 3, 4 and the loop finally stops at 4.

Solutions:

const arr = [10, 12, 15, 21];
for (var i = 0; i < arr.length; i++) {
  // pass in the variable i so that each function 
  // has access to the correct index
  setTimeout(function(i_local) {
    return function() {
      console.log('The index of this number is: ' + i_local);
    }
  }(i), 3000);
}
const arr = [10, 12, 15, 21];
for (let i = 0; i < arr.length; i++) {
  // using the ES6 let syntax, it creates a new binding
  // every single time the function is called
  // read more here: http://exploringjs.com/es6/ch_variables.html#sec_let-const-loop-heads
  setTimeout(function() {
    console.log('The index of this number is: ' + i);
  }, 3000);
}

Question #2: Event delegation

<ul id="todo-app">
  <li class="item">Walk the dog</li>
  <li class="item">Pay bills</li>
  <li class="item">Make dinner</li>
  <li class="item">Code for one hour</li>
</ul>
document.addEventListener('DOMContentLoaded', function() {
  let app = document.getElementById('todo-app');
  let items = app.getElementsByClassName('item');
  // attach event listener to each item
  for (let item of items) {
    item.addEventListener('click', function() {
      alert('you clicked on item: ' + item.innerHTML);
    });
  }
});

Write an optimize event delegation to bind event on 10,000 elements

Solution:

document.addEventListener('DOMContentLoaded', function() {
  let app = document.getElementById('todo-app');
  // attach event listener to whole container
  app.addEventListener('click', function(e) {
    if (e.target && e.target.nodeName === 'LI') {
      let item = e.target;
      alert('you clicked on item: ' + item.innerHTML);
    }
  });
});

Question #3: Debouncing

Note:

There are some browser events that can fire many times within a short timespan very quickly, such as resizing a window or scrolling down a page. If you attach an event listener to the window scroll event for example, and the user continuously scrolls down the page very quickly, your event may fire thousands of times within the span of 3 seconds. This can cause some serious performance issues.

Debouncing is one way to solve this issue by limiting the time that needs to pass by until a function is called again. A correct implementation of debouncing would therefore group several function calls into one and execute it only once after some time has elapsed. Here’s an implementation in plain JavaScript that makes use of topics such as scope, closures, this, and timing events:

Throttling is another technique that’s is similar to debouncing, except that instead of waiting for some time to pass by before calling a function, throttling just spreads the function calls across a longer time interval. So if an event occurs 10 times within 100 milliseconds, throttling could spread out each of the function calls to be executed once every 2 seconds instead of all firing within 100 milliseconds.

https://css-tricks.com/the-difference-between-throttling-and-debouncing/
function debounce(fn, delay) {
  // maintain a timer
  let timer = null;
  // closure function that has access to timer
  return function() {
    // get the scope and parameters of the function 
    // via 'this' and 'arguments'
    let context = this;
    let args = arguments;
    // if event is called, clear the timer and start over
    clearTimeout(timer);
    timer = setTimeout(function() {
      fn.apply(context, args);
    }, delay);
  }
}

You would use this function like so:

// function to be called when user scrolls
function foo() {
  console.log('You are scrolling!');
}
// wrap our function in a debounce to fire once 2 seconds have gone by
let elem = document.getElementById('container');
elem.addEventListener('scroll', debounce(foo, 2000));

Question #4. Explain the difference between classical inheritance and prototypal inheritance.

Answer: The great thing about JavaScript is the ability to do away with the rigid rules of classical inheritance and let objects inherit properties from other objects.

Classical Inheritance: A constructor function instantiates an instance via the “new” keyword. This new instance inherits properties from a parent class.

Prototypal Inheritance: An instance is created by cloning an existing object that serves as a prototype. This instance—often instantiated using a factory function or “Object.create()”—can benefit from selective inheritance from many different objects.

Question #5. What is a RESTful Web Service?

Answer:

REST stands for Representational State Transfer, an architectural style that has largely been adopted as a best practice for building web and mobile applications. RESTful services are designed to be lightweight, easy to maintain, and scaleable. They are typically based on the HTTP protocol, make explicit use of HTTP methods (GET, POST, PUT, DELETE), are stateless, use intuitive URIs, and transfer XML/JSON data between the server and the client.

Question #6. Explain the differences between one-way data flow and two-way data binding.

Answer:

In two-way data binding, changes to the UI and changes to the model occur asynchronously—a change on one end is reflected on the other. In one-way data binding, data only flows one way, and any changes that the user makes to the view will not be reflected in the model until the two are synced. Angular makes implementing two-way binding a snap, whereas React would be your framework of choice for deterministic one-way data flow.

Question #7. Determine the output of the code below. Explain your answer.

console.log(0.1 + 0.2);
console.log(0.4 + 0.1 == 0.5);

Question #8. What will be the output of following code? Explain.

var myObject = {
  egg: "plant",
  func: function() {
    var self = this;
    console.log("outer func: this.egg = " + this.egg);
    console.log("outer func: self.egg = " + self.egg);
    (function() {
      console.log("inner func: this.egg = " + this.egg);
      console.log("inner func: self.egg = " + self.egg);
      }());
  }
};
myObject.func();

Question #9. Write a function that can determine whether a string is a palindrome in under 100 characters.

Soluction:

A palindrome is a word, phrase, or sequence of letters that reads the same backwards or forwards. It also makes a great test for checking their ability to handle strings.

function isPalindrome(str) {
    str = str.replace(/s/g, '').toLowerCase();
    return (str == str.split('').reverse().join(''));
}

Question #10. How would you empty the array below?

Var emptyArray = [‘this’, ‘array’, ‘is’, ‘full’];

Solution:

emptyArray.length = 0;
emptyArray.splice(0, emptyArray.length);
while(emptyArray.length){
    emptyArray.pop();
}
emptyArray = []

Question #11. Determine the output of the code below. Explain your answer.

var lorem = { ipsum : 1};
var output = (function(){
  delete lorem.ipsum;
  return lorem.ipsum;
})();

console.log(output);

Explaination:

The output would be undefined, because the delete operator removed the property “ipsum” from the object “lorem” before the object was returned. When you reference a deleted property, the result is undefined.

Question #12. Find duplicate elements from array.

var a = [1,2,3,1,6,6]

Solutions: If value of elements of array are less than length of array. For the given problem a has elements less than its length. Then we can find like this:

function printRepeat(arr) {
	for (var i = 0; i < arr.length; i++) {
		if (arr[Math.abs(arr[i])] >= 0) {
			arr[Math.abs(arr[i])] = -arr[Math.abs(arr[i])];
		} else console.log('Element is ', Math.abs(arr[i]))
	}
}

Find explation for above solution here: https://www.geeksforgeeks.org/find-duplicates-in-on-time-and-constant-extra-space/

a.filter((b, i) => a.indexOf(b) !== i)

Question #13. Deep clone Object.

var b = 10 var obj = { a: 13, b: b }

Solutions:

JSON.parse(JSON.stringify(obj))
function keepCloning(objectpassed) {
  if (objectpassed === null || typeof objectpassed !== 'object') {
     return objectpassed;
  }
// give temporary-storage the original obj's constructor
var temporary-storage = objectpassed.constructor(); 
  for (var key in objectpassed) {
    temporary-storage[key] = keepCloning(objectpassed[key]);
  }
  return temporary-storage;
}
var employeeDetailsOriginal = {  name: 'Manjula', age: 25, Profession: 'Software Engineer' };
var employeeDetailsDuplicate = (keepCloning(employeeDetailsOriginal));
employeeDetailsOriginal.name = "NameChanged";
console.log(employeeDetailsOriginal);
console.log(employeeDetailsDuplicate);

Question #14. What is prototype chaining?

Answer:

Prototype chaining is used to build new types of objects based on existing ones. It has a very similar job to inheritance in a class based language.

Constructor functions have a property called prototype. Adding properties and methods to the prototype property will automatically add the method or property to all objects created by the constructor function.

Prototype chaining is an extension of this idea. The prototype property is just a regular javascript object so it’s possible to create a function’s prototype using another constructor function. When you do this, all of the properties and methods from the constructor function’s prototype are automatically added to new the prototype object. This makes it easy to create a constructor function that builds objects that are an extended version of an existing one.

For a simple example, imagine that you have a Pet constructor to make pet objects. Now you want to make Cat that is pretty much like a Pet but has a few differences.

Here’s the Pet constructor function from the prototype example:

function Pet(name, species, hello) {
    this.name = name;
    this.species = species;
    this.hello = hello;
}
 
Pet.prototype = {
    sayHello : function() {
        alert(this.hello);
    }
}

We can give the cat all the properties of the Pet by setting it’s prototype to be a new pet object:

function Cat(name, hello, breed, whiskerLength)
{
    this.name = name;
    this.species = species;
    this.hello = hello;
    this.breed = breed;
    this.whiskerLength = whiskerLength;
}
 
Cat.prototype = new Pet();
var rufus = new Cat("rufus", "miaow", "Maine Coon", 7);
rufus.sayHello();

Question #15. Find second largest from array.

var arr = [20, 120, 111, 215, 54, 78];

Solution:

arr.sort(function(a, b) { return b - a })[1]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment