Categories
JavaScript Interview Questions

JavaScript Interview Questions — Harder DOM Questions

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

In this article, we’ll look at some harder questions about DOM manipulation.

How to check if an element is a descendant of a parent element?

We can use the parentNode property of a DOM element to check if an element is a child of another element.

For example, we write the following function check if a node is a parent of a child node:

const isDescendant = (parent, child) => {
  while (child.parentNode) {
    if (child.parentNode == parent)
      return true;
    else
      child = child.parentNode;
  }
  return false;
}

In the isDescendant function, we get the parent node of the child with the parentNode property until we reach the top level.

In each parent, we check if the parentNode property references the same node as the parent .

We return true if that’s the case. Otherwise, we go top the grandparent, great-grandparent and all the way to the top level and return true if we find that parentNode is the same node as parent.

Otherwise, we return false if none of them are the same as parent.

For example, if we have the following HTML:

<div>
  <p>
    <span></span>
  </p>
</div>

<div id='foo'></div>

Then if we have the following code:

const div = document.querySelector('div');
const p = document.querySelector('p');
const span = document.querySelector('span');
const foo = document.querySelector('#foo');

console.log(isDescendant(div, p));
console.log(isDescendant(div, span));
console.log(isDescendant(foo, span));

The first 2 should log true and the last one should false since the first div is the parent of p and grandparent of the span.

The div with ID foo isn’t a parent of any of the other nodes.

What’s the difference between innerHTML and appendChild?

innerHTML removes all current child nodes of the elements. Then the JavaScript interpreter parses the string and then assigns the parsed string to the element as the children.

appendChild attaches the child node to the parent node it’s called on as the name suggests.

For example, if we have the following HTML:

<div>
  <p>foo</p>
</div>

Then if we write:

const div = document.querySelector('div');
div.innerHTML = '<p>bar</p>';

Then we only see ‘bar’ on the screen since we set the innerHTML property to overwrite what’s there.

On the other hand, if we use appendChild as follows:

const div = document.querySelector('div');

const p = document.createElement("p");
const bar = document.createTextNode("bar");
p.appendChild(bar);

div.appendChild(p);

Then we add the p element with the text node ‘bar’ and the call appendChild to append p to the div , we see:

foo

bar

displayed on the screen since we added a new child to the end of the list of child elements to the div.

What is createDocumentFragment and why you might use it?

document.createDocumentFragment lets us create a new DocumentFragment in which DOM nodes can be added to build an offscreen DOM tree.

For example, if we have the following HTML:

<ul></ul>

Then we can use createDocumentFragment as follows to create an offscreen fragment and then insert the whole thing into the DOM:

const element = document.querySelector('ul');
const fragment = document.createDocumentFragment();
const fruits = ['apple', 'orange', 'grape'];

fruits.forEach((fruit) => {
  const li = document.createElement('li');
  li.textContent = fruit;
  fragment.appendChild(li);
});

element.appendChild(fragment);

With createDocumentFragment , we added all the nodes to fragment first and then append the whole thing to our ul element with appendChild .

DocumentFragment is a lightweight or minimal part of a DOM or a DOM subtree. It’s useful for manipulating the part of the DOM multiple times.

DocumentFragments are managed in memory so that the CPU won’t be taxed by expensive operations.

What is reflow? What causes reflow? How could we reduce reflow?

Reflow is the situation where we change the position of the elements according to screen size or position changes.

If we change the width of the screen, like when we’re rotating the phone’s screen, then everything has to be moved to display in the screen property.

Reflows are expensive since everything has to be moved, especially on smaller devices like phones.

Reflows are caused by changing layout, resizing the window, changing the dimension of any element, changing fonts in any way, moving DOM elements, adding or removing stylesheets, and anything else that make similar kinds of changes.

To avoid reflow, we avoid setting multiple inline styles, apply animations to elements that fixed or absolute position, and avoid using tables for layout.

Conclusion

We can use the parentNode property of a node to get the parent of a node.

Setting the innerHTML property of an element overwrites all the existing children and replace them with new ones from the string we set.

appendChild attaches a new child element to the end of the subtree.

DocumentFragments are lightweight offscreen elements that hold DOM elements. It’s managed in memory and can be added to the screen like any other element.

Reflow is the position change of elements according to some other changes on the screen. It’s an expensive operation that should be avoided.

Categories
JavaScript Interview Questions

JavaScript Interview Questions — The DOM

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

In this article, we’ll look at some questions about DOM manipulation.

What’s the difference between window vs document?

The difference between window and document is that document is a property of the window object.

window is the JavaScript global object that has everything including global functions, location, history, web components, setTimeout , XMLHttpRequest , console , localStorage and much more.

document represents the DOM of the page. The DOM represents the HTML markup that was written or generated.

With document , we have methods to traverse the DOM like getElementById , querySelector , removeChild, appendChild and more.

What’s the difference between window.onload vs document.onload?

window.onload is fired when the DOM is ready and all the content including images, CSS, scripts, subframes, etc. finish loaded.

It means that everything is loaded.

document.onload is fired when the DOM is ready, which can be before images and other external content is loaded.

document.readyState returns 'loading' when the document is loading, 'interactive' once it’s finished parsing but stilling loading subresources, and 'complete' once it’s completely loaded.

The readystatechange event is fired when the readyState is changed.

What’s the difference between an attribute and a property?

Attributes represent the attributes in HTML elements inside the starting tag.

They’re exposed to the DOM via a property, Properties of the JavaScript DOM objects are created when the DOM is parsed for each attribute in the HTML tag.

If an attribute is changed, the value of the property will change. On the other hand, if we change the property in the JavaScript DOM object, the attribute will stay the same.

What are the methods to get one or more elements from the DOM?

Browsers provide us with multiple methods to get elements from the DOM.

They’re the following:

getElementById

geteElementById returns an element with the given ID.

getElementsByClassName

getElementsByClassName gets a NodeList array-like object, which is an object with entries that have indexes and a length property by passing in a string with the class name.

getElementsByTagName

getElementsByTagName gets a NodeList by passing in a tag name.

querySelector

querySelector gets a DOM Node by passing in a CSS selector string.

querySelectorAll

querySelectorAll gets a NodeList by passing in a CSS selector string.

getElementsByName

getElementsByName returns a list of elements by the provided name of the HTML tag

getElementsByTagNameNS

getElementsByTagNameNS returns elements with a particular tag name within the provided namespace.

What’s the fastest way to query DOM?

The fastest way to select an element is by ID if the ID exists.

The second quickest is getElementByClassName .

The longer the selector, the slower it will be.

querySelectorAll will be the slowest since it has to search for all kinds of CSS selectors.

Other methods like getElementById and getElementsByTagName only search for specific kinds of selectors.

How do we use forEach and other array methods on a NodeList?

We can use the spread operator to convert the NodeList to an array, then we can use forEach or any other array method we want with the NodeList.

We can do this since it’s an array-like object.

For example, if we have the following HTML:

<div>foo</div>
<div>bar</div>
<div>baz</div>

Then we can get and loop through the divs by running:

[...document.querySelectorAll('div')].forEach(div => console.log(div.textContent));

Then we’ll get:

foo
bar
baz

from the console.log .

How do we implement a function to get elements by attribute?

We can implement the function easily with document.querySelectorAll by using a CSS selector with the given attribute and value:

const getElementsByAttribute = (attribute, value) => {
  return [...document.querySelectorAll(`[${attribute}=${value}]`)];
}

Therefore, if we’re given the following HTML:

<div id='foo'>foo</div>
<div>bar</div>
<div>baz</div>

We’ll see an array with the div with ID foo returned.

How do we implement a function to add a class to an HTML element?

We can write the following function to add a class to an element:

const addClass = (selector, className) => {
  const elm = document.querySelector(selector);
  if (elm) {
    elm.classList.add(className);
  }
}

In the code above, we used querySelector to get a single element. Then if the element with the given selector exists, we use the classList property’s add method to add a new class name to the element.

For example, given that we have the following HTML:

<div>foo</div>
<div>bar</div>
<div>baz</div>

The first div will have the foo class added if we run:

addClass('div', 'foo');

Conclusion

We can select DOM elements and manipulate their properties.

They’re from the attributes that we have written in the HTML code or generated on the fly with JavaScript.

document represents the page and window is the parent object for document .

Categories
JavaScript Interview Questions

JavaScript Interview Questions — Operators

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

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

What does the && operator do?

The && operator is the logical AND operator and finds the first falsy expression in its operands and returns it.

For example, if we have:

console.log(0 && 1 && "foo");

Then we get 0 logged since 0 is the first falsy expression in the operands.

What does the || operator do?

The || operator is the logical OR operator and finds the first truthy expression in its operands and returns it.

For example, if we have:

console.log("" || "foo" || false);

Then we get 'foo' logged because it’s the first truthy operand in the expression.

It’s also useful for providing a default value if the ones before it are falsy.

What does the + operator do?

The + operator converts whatever is after it to a number if it’s placed before an expression. So if we have:

console.log(+"1");

Then we get 1 logged.

If we have:

console.log(+("1" + 2));

Then we get 12 logged.

As we can it also serves as the concatenation operator for strings within the parentheses.

It’s also the addition operator if all operands are numbers.

For example, if we have:

console.log(1 + 2 + 3);

Then we get 6.

What does the ! operator do?

The ! operator converts the operand to a boolean and negates it. It’ll convert falsy values true and truthy value to false .

For example, if we have:

console.log(!0);
console.log(!"");
console.log(!false);
console.log(!NaN);
console.log(!undefined);
console.log(!null);

then they all log true .

If ! is placed before a truthy expression then it’ll log false .

For example, if we have:

console.log(!`1`);

Then we’ll see false logged.

What does the !! operator do?

!! is the double NOT operator, which coerces the operand to a boolean value. It’ll convert truthy values to true and falsy values to false .

For example, if we have:

console.log(!!0);
console.log(!!'');
console.log(!!false);
console.log(!!NaN);
console.log(!!undefined);
console.log(!!null);

They’ll log false .

Applying !! before any truthy expression should return true .

For example:

console.log(!!{});

logs true .

What’s the rest operator?

The spread operator is denoted by ... .

We can use it to assign objects or array entries that haven’t been assigned during destructuring into a variable with an array of the remaining values.

If the object is a variable, we can use the rest operator to assign the properties that haven’t been assigned to an object into a variable containing the remaining properties of the original object.

For example, if we have:

const [one, two, ...rest] = [1, 2, 3, 4, 5, 6];
console.log(one);
console.log(two);
console.log(rest);

Then one is 1 and two is 2, and rest has [3, 4, 5, 6] .

It can also be used to spread objects into variables. For instance, we can do that as follows:

const { foo, bar, ...rest } = { foo: 1, bar: 2, a: 3, b: 4, c: 5 };
console.log(foo);
console.log(bar);
console.log(rest);

Then foo is 1, bar is 2, and rest has {a: 3, b: 4, c: 5} .

We can also use it to get the arguments passed into a function that hasn’t been assigned to its own parameter as an array. For example, we can write:

const foo = (a, b, ...rest) => console.log(rest);
console.log(foo(1, 2, 3, 4, 5));

Then console.log should log [3, 4, 5] for rest .

What’s the spread operator?

The spread operator is also indicated by the ... operator. It’ll spread an object’s property into another object and spread the array entries into another array.

For example, if we have:

const foo = [1, 2, 3];
const bar = [...foo];
console.log(bar);

Then we get [1, 2, 3] as the value of bar since we made a copy of foo and assigned it to bar with the spread operator.

It’s also useful for merging arrays. For instance, if we have:

const foo = [1, 2, 3];
const bar = [3, 4, 5];
const baz = [...foo, ...bar];
console.log(baz);

Then baz would be [1, 2, 3, 3, 4, 5] since we combined the entries of the foo and bar arrays into the baz array.

The spread operator also works for objects. It’ll make a shallow copy of an object or merge multiple objects into one. If 2 objects have the same property when merging, then the one that’s merged later will overwrite the first one.

For example, if we have:

const foo = { a: 1, b: 2, c: 3 };
const bar = { a: 2, d: 4, e: 5 };
const baz = { ...foo, ...bar };
console.log(baz);

Then baz is {a: 2, b: 2, c: 3, d: 4, e: 5} since bar is merged in later so property a us 2.

The spread operator is also used to spread an array into a list of arguments in a function.

For example, if we have:

const add = (a, b) => a + b;
console.log(add(...[1, 2, 3, 3, 4, 5]));

Then the console.log will show 3 because the 1 and 2 from the array were assigned to the a and b parameters by the spread operator.

Conclusion

The && , || , ! , and !! are logical operators.

The && operator is the logical AND operator and finds the first falsy expression in its operands and returns it.

The || operator is the logical OR operator and finds the first truthy expression in its operands and returns it.

The ! operator coerce an expression to a boolean then negates it.

The !! operator coerce an expression to a boolean without negation.

The + operator can be convert expressions to numbers, add numbers, or concatenate strings.

The rest operator is useful for getting the remaining parts of an array or object.

The spread operator is useful for merging objects and arrays or making copies of them. It can also be used to pass an array into a function as arguments.

Categories
JavaScript Interview Questions

JavaScript Interview Questions — Functional Programming

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

In this article, we’ll look at some functional programming questions of JavaScript.

What is Functional Programming? What makes JavaScript a Functional Language?

Functional programming is a programming paradigm that dictates the way we build apps. Functional programming treats functions in programs like mathematical functions.

This means that we avoid changing state and creating mutable data. It also means that functions are pure, that is, a function that returns the same thing given the same input.

Functions also shouldn’t have side effects in functional programming because it makes functions impure.

JavaScript functions are also first-class functions. This means that we can have functions that have functions as arguments or functions that return functions.

It also supports closures, where we return functions that can use some values inside the parent function.

For example, JavaScript arrays have the map, filter, and reduce methods, which take callback functions that are called as they process the items in the array.

map, filter, and reduce are higher-order functions since they accept functions as arguments. Functions that return functions are also higher-order functions.

For example, the map method can be used as follows:

const nums = [1,2,3];
const doubleNums = nums.map(x => x*2);

In the code above, we passed in the function x => x*2 into map .

x => x*2 does the computation as specified by the code on each entry, and then return a new array with the new values. Then we get that doubleNum is [2, 4, 6] .

What are Higher Order Functions?

Higher-order functions are functions that take functions as arguments or return functions.

For example, if we have:

const hoc = (fn)=> fn();
hoc(()=>{
 console.log('foo');
});

The code above has the hoc function which takes a function fn and runs it.

Then when we make the following call:

hoc(()=>{
 console.log('foo');
});

Then we get foo logged since the function we passed in is run in the hoc function.

Why are functions called First-class Objects?

JavaScript functions are first-class objects because they’re treated like any other kind of object.

This means that functions can be stored in a variable, object or array. They can be passed into functions as arguments. Also, they can be returned from the function.

For example, we can assign functions to variables as follows:

let foo = () => {};

We assigned an arrow function to the variable foo .

Also, they can be passed in as argument as follows:

let foo = () => {
 console.log('foo');
};
let bar = (fn) => fn();
bar(foo);

Then we can call bar with foo passed in. Note that we just pass in the reference of foo , we don’t call it. Therefore, there are no parentheses following foo .

They can be returned by a function as follows:

let foo = () => {
 return ()=> console.log('foo')
};
`
foo()();

the foo function above returns a function that logs 'foo' .

Then we call it as we did in the last line.

JavaScript functions can also be stored in objects and arrays. For example, we can write:

let obj = {
  foo: () => {
    console.log("foo");
  }
};
obj.foo();

We put the foo function inside an object as a property then called it in the last line.

Finally, we can store them in an array as follows:

const arr = [
  () => {
    console.log("foo");
  }
];
`
arr[0]();

or we can call push to put it in the array:

const arr = [];
`
arr.push(() => {
  console.log("foo");
});
`
arr[0]();

What is the arguments object?

The arguments object is an array-like object that has the arguments that we pass into a function. Array-like means that it has the length property and we can loop through the items by using an index to get the item, but it doesn’t have any array methods like map , reduce , or filter included with it.

It only gets the arguments of traditional functions.

For example, we can write:

function foo() {
  console.log(arguments);
}
`
foo(1, 2, 3, 4, 5);

Then the console.log will return us the arguments that we passed into foo , which is 1, 2, 3, 4, and 5.

Arrow functions don’t bind to the arguments object, so we can’t get all the arguments passed into an arrow function with this object.

The for...of loop also works with the arguments object, so we can loop through the arguments as follows:

function foo() {
  for (let arg of arguments) {
    console.log(arg);
  }
}
`
foo(1, 2, 3, 4, 5);

We can use the spread operator to convert arguments into an array. For example, we can write:

function foo() {
  console.log([...arguments]);
}
`
foo(1, 2, 3, 4, 5);

Then we get [1, 2, 3, 4, 5] logged.

Conclusion

JavaScript has lots of functional programming features. Functions are first-class objects, which means that they’re treated like any other object.

It also has the quirky, array-like arguments to get the arguments that are passed into a traditional function.

Categories
JavaScript Interview Questions

JavaScript Interview Questions — 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 object questions.

How to check if a certain property exists in an object?

There’re a few ways to check if a property exists in an object.

First, we can use the in operator. For example, we can use it as follows:

const foo = { a: 1 };
console.log('a' in foo);

The in operator checks if the property with the given name exists in the object itself or its prototypes in the prototype chain.

The code above should return true since a is a property of foo .

console.log(‘toString’ in foo); should also log true since toString is in the Object ‘s prototype, which foo inherits from.

We can also use the Object.prototype.hasOwnProperty method. For example, we can use it as follows:

const foo = { a: 1 };
console.log(foo.hasOwnProperty('a'));

The code above uses the hasOwnProperty method in foo ‘s prototype to check if a exists in foo and its own property, which means that it’s in foo itself rather than its prototype.

The console.log logs true since a is foo ‘s own property.

Finally, we can check using the bracket notation as follows:

const foo = {
  a: 1
};
console.log(foo['a']);

If it returns the value other than undefined , then we know we added it as a property.

Since this is the case with our example, it should return true .

What’s the difference between Object.seal and Object.freeze methods?

After calling Object.seal on an object, we stop properties from being added to the object.

It also makes all existing properties non-configurable, which means the property descriptors are prevented from changing.

Existing properties also can’t be removed with the delete operator after it’s called on an object.

The object’s __proto__ property, which is the object’s prototype, is also sealed.

For example, if we have:

const foo = {
  a: 1
};
Object.seal(foo);
delete foo.a

We’ll still see foo.a after we run the last line.

If we’re in strict mode, we’ll get an error.

Object.freeze makes the object immutable. Existing properties can’t be changed in any way, including the values of each property.

It also does everything that Object.seal does.

What’s the difference between the in operator and the hasOwnProperty method in objects?

The in operator checks if a property is in the object itself and if it’s in its prototypes up the prototype chain.

On the other hand, hasOwnProperty only checks if an object is inside the object that it’s called on and not any of its prototypes.

Why does typeof null return object?

null has type object because it’s how it acts in early versions of JavaScript. It just stays this way to prevent breaking existing codebases.

How to check if a value is null?

We should use the strict equality operator to check for null as follows:

foo === null

What does the new keyword do?

The new keyword is used to create an object from constructor functions or classes.

For example, if we have a Person class:

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

Then we can create a new instance of it by writing:

const person = new Person("Jane", "Smith");

new does a few things:

  • It creates an empty object
  • Assigns the empty object to the this value
  • The function inherits from the prototype property of the constructor function. So Person inherits from Person.prototype .
  • If there’s no return statement in the function, then it’ll return this .

Note that the class syntax in ES2015 or later is just syntactic sugar for constructor functions. It does the same thing but looks like a class.

Conclusion

We can check if a property exists in an object with the in operator, hasOwnProperty , or bracket notation.

Object.seal prevent property descriptors from changing and properties from being deleted.

Object.freeze makes an object immutable.

null is of type object rather than having its own type.

The new keyword makes a new object from a constructor function and returns it.