Interview Questions for a Front-End Developer

LikiMS
Liki Blog
Published in
15 min readApr 15, 2020

--

Everyone has had a job interview in their career. Some of Liki developers have the opportunity to experience it from the interviewer’s perspective. Thus, we decided to share the set of common questions collected by our FrontEnd team members who are actively involved in the recruitment process. Krzysztof Wyrzykowski, Adrian Wolański, Marcin Skrzyński and Michał Łyczko prepared the set of the most common questions you may be asked when applying for a Front-end Developer or other programming positions in a Software House. We believe this collection will help you to verify your technical knowledge and get the gist of what are the expectations during an interview in Liki and many other Software Houses. The questions (plus answers!) are categorized according to the areas of Angular, React, HTML and CSS. This article may serve as a mini dictionary of contemporary frontend terms. Afterward, you should be able to state what you remember and what else you should make up for. Enjoy the reading.

Recruitment conversation in Liki.

ANGULAR

What are the differences between the components and the directives?

A directive is a mechanism by which we attach the behavior to the elements of a DOM, which consists of structural types, attributes and components. A component is the specific type of directive that allows us to use the functionality of the components — hermetic reusable elements available in our application. It is worth adding that the component is one of the types of directives. However, unlike directives, components will always have their own template. It should also be remembered that only one component can be initialized ‘per element’ in the template.

What is NgModule?

Modules (ngModules) are the logical boundaries in an application. They are used to divide the application in order to identify its functionality. An angular module adopts the following options in the decorator:

  • imports — serve to import dependencies in the form of modules.
  • declarations — define the components used within the given module.
  • providers — inject instructions for the DI system. They describe the value for a given dependency that a supplier has to obtain. In most cases, this array will adopt a service class.
  • entryComponents — this array is used to declare dynamically loaded components that were not used during the compilation process and were not compiled by the offline compiler (OTC).
  • bootstrap — an option in which we declare the so-called root, i.e. a component that will be embedded in index.html.

What does the component’s life cycle look like?

The component in Angular has a life cycle — a number of different phases that pass from “birth” to “death”. What’s more, we can connect to the different phases in order to gain the greatest possible control over our application. Their visual representation is as follows:

  • constructor — when Angular creates a component or a directive, the constructor calls new within the class.
  • ngOnChanges — this method is called when the value of a data-related property changes.
  • ngOnInit — occurs every time we initiate a directive/ component.
  • ngDoCheck — is called up together with the given component’s change detector. In this way we can implement our own change detection algorithm for a given component.

Remember: ngDoCheck and ngOnChanges should not be implemented together on the same component.

  • ngOnDestroy — this method will be called just before Angular destroys the component.

Methods that are supported only by the components:

  • ngAfterContentInit — is called up after Angular projects external content into the component’s view.
  • ngAfterContentChecked — it’s called each time Angular change detection mechanism checks the content of a given component.
  • ngAfterViewInit — called when the component view has been fully initiated.
  • ngAfterViewChecked — it’s called each time the view of a given component has been checked by the Angular’s change detection mechanism.

Types of metadata

Metadata is used to “decorate” the class so that the expected behavior can be configured. The metadata is represented by the so-called decorators. We extract metadata types, such as:

Class decorator, e.g. @Component or @NgModule.

Property decorator, e.g. @Input or @Output.

Method decorator, e.g. @HostListener.

Parameter decorator, e.g. @Inject.

Guards / Resolvers

Guards are implemented as services that should be provided, so we usually create them as @Injectable classes. Guards will return true value if the user has access to a route, or false value if the user has no access. Guards can also return Observable or Promise, which later turn into boolean value when the guard cannot answer the question immediately, for example, it may need to call the API. Angular will allow the user to wait for the guard to return true or false value.

There are 4 types of guards:

CanActivate — checks if you can visit the route.

CanActivateChild — checks if the user can visit the child route.

CanDeactivate — checks if the user can leave route.

CanLoad— checks if the user can download a module that is lazy-loaded.

There is also a special type:

Resolve — it fetches data before activating the route. It is most often used to download/inject data necessary for the next route.

Change detection strategy in the component

This is the strategy that the default change detector performs to detect changes. When set, it takes effect the next time change detection is triggered.

We can set two different types of change detection strategies:

Default — the default CheckAlways strategy, in which change detection is automatic until it is explicitly deactivated.

OnPush — CheckOnce strategy, which means that automatic change detection is deactivated until it is reactivated by setting the strategy to Default (CheckAlways). Change detection can still be explicitly invoked. This strategy applies to all subordinate directives and cannot be replaced.

RxJS in the context of Angular — what should you know?

At this point it is worth mentioning the difference between Observable and Promise. In Angular we can use both to work with asynchronous data. However, there are some differences.

1. Promise returns a single value (resolve) or an error (reject), whereas Observable is used to work with events and data streams, which are perfect for handling many values (although they can also be used for single values).

2. The second difference is that Promise — unlike Observable — cannot be cancelled. If we have some pending HTTP request, and we no longer need the data, we can cancel this request by unsubscribing.

```

// stream$ is in ex. some expensive HTTP call….

const subscription = stream$.subscribe(() => doSomething());

// … when we don’t need it anymore

subscription.unsubscribe();

```

3. Observable, unlike Promise, is lazy which means that the code in the body of the function will not be executed until we start listening — in other words, subscribing.

Let’s take a look at the following example of Promise vs Observable and the console.logs. They will be returned in case of commenting then, as well as Promise and subscribe to Observable. Here are the examples:

PROMISE:

const promise = new Promise(resolve => {

setTimeout( () => {

console.log(‘Some code in promise…’);

resolve(1);

}, 500);

console.log(‘Promise started…’);

});

promise.then(val => console.log(‘Value from promise:’, val));

console.log:

Promise started…

Some code in promise…

Value from promise: 1

After commenting `then()`:

const promise = new Promise(resolve => {

setTimeout( () => {

console.log(‘Some code in promise…’);

resolve(1);

}, 500);

console.log(‘Promise started…’);

});

// promise.then(val => console.log(‘Value from promise:’, val));

console.log:

Promise started…

Some code in promise…

OBSERVABLE:

const stream$ = rxjs.Observable.create((observer) => {

setTimeout( () => {

console.log(‘Some code in observable…’);

observer.next(1);

observer.complete();

}, 500);

console.log(‘Observable started…’);

});

stream$.subscribe(val => console.log(‘Value from observable:’, val));

console.log:

Observable started…

Some code in observable…

Value from observable: 1

After commenting `subscribe()`:

const stream$ = rxjs.Observable.create((observer) => {

setTimeout( () => {

console.log(‘Some code in observable…’);

observer.next(1);

observer.complete();

}, 500);

console.log(‘Observable started…’);

});

// stream$.subscribe(val => console.log(‘Value from observable:’, val));

console.log:

(empty)

Preview: https://jsfiddle.net/lyczos/sr4uzybL/28/

The streams in Angular is another significant issue to explore. The following questions may refer to this area:

When to use unsubscribe?

When we no longer need the data from a stream, we should remember to “kill” the subscription to that stream to avoid memory leaks. However, in Angular, there are some situations where we don’t have to worry about manual unsubscribing. Here’s a list of these situations:

  • We don’t have to ‘unsubscribe’ from observables that end (complete) or return an error. However, there is nothing wrong with that! :)
  • We don’t have to worry about memory leaks in the case of observables, which are spread to the whole application, i.e. subscriptions to services. Why? Services in Angular are singletones, which means that the service exists in the application as long as the whole application lives. As a result, there is no possibility of memory leakage.
  • Async pipe, or when a component is destroyed, async will destroy the subscriptions itself.
  • We should use HostListener as a way to listen to the events, because then Angular deals with removing eventListeners for us and prevents memory leaks caused by event binding.

When do we have to remember that?

  • We should always ‘unsubscribe’ from observables FromGroup (form.valueChanges, from.statusChanged)
  • As well as from observables Renderer2, e.g. renderer2.listen

In other questions in this area we may be asked to clarify the following terms:

RxJS: Understanding Higher-Order Mapping Operators

They are used to map values to Observable. What does this mean and what can it be useful for? Imagine that you want to pass a click position (clientX) to the API. Let’s look at two examples: the first one (incorrect), without the High-order mapping operator, and the second one (concatMap):

They are used to map values to Observable. What does this mean and what can it be useful for? Imagine that you want to pass a click position (clientX) to the API. Let’s look at two examples: the first one (incorrect), without the High-order mapping operator, and the second one (concatMap):

click$.pipe(

map(event => event.clientX)

).subscribe(x => {

console.log(‘X’, x);

// some api call:

api.saveClick(x).subscribe(response => {

// NESTED SUBSCRIPTION:!!

console.log(‘data saved: ‘, response);

});

});

click$.pipe(

map(event => event.clientX),

tap(x => console.log(‘X’, x)), // debug

concatMap((x) => api.saveClick(x)) // high-order mapping operator

).subscribe(response => {

console.log(‘data saved: ‘, response);

});

The result of both examples is the same, but as we can see, the latter one is much more readable ;)

Which Higher-Order Mapping Operators do you know?

concatMap, exhaustMap, switchMap, mergeMap

React

Which design patterns in React do you know?

HOC — High Order Component is a function that takes a component as a parameter and returns a new one.

Destructuring props is the destructuring of an object to a single property.

```

const Greeting = ({ id, name }) => {

return <div id={id}>Hello, { name }</div>

}

```

Function component is the easiest way to create a React component.

```

function Howdy() {

return <span>Howdy!</span>

}

```

JSX spread attributes / forward props it is to use some props and pass them on.

```

const Greet = ({ name, …restProps }) => {

return (

<div { …restProps }>

Hello, { name }

</div>

)

}

```

Render props is responsible for transferring the function that will be the content of our component.

```

// Initialization

const Greet = ({ render, …restProps }) => {

const name = „Jake”;

return render(name)

)

// Usage

<Greet render={name => (

<div>Hello, {name}</div>

)} />

```

All of these things allow us to get to the data from the component and display it in any way we want, without changing the logic of the component.

At the interview,you may also have open questions. That’s why you should be able to say a few sentences about some terms.

Tell me what you know about HOC.

High Order Component is a function that takes a component as a parameter and returns a new one. It does this by adding its own props, wrapping it in a wrapper or performing other operations on it. This technique can be used extensively with ‘Redux’, namely when using the connect function to inject actions and props into a component.

How does Virtual DOM work and what are its advantages/ disadvantages? What do you know about React Reconciliation?

Virtual DOM is an object that represents the state of the DOM tree. It is used to observe changes in application structure and render them into the DOM tree. The main advantage is that you can precisely determine if there are any changes to our application. Thanks to this we can render a specific part of an application. This improves the performance and all the nodes that are not part of a render remain unchanged.

The disadvantages include the need for constant control over the changes and the need to keep the whole DOM object in memory.

React Reconciliation is a complex mechanism for rendering JSX objects in the DOM tree, which employs a comparative algorithm, the so-called Diffing Algorithm.

It allows responding to changes related to the JSX element and re-rendering a given node in the DOM tree. This mechanism also includes mapping of HTML attributes, such as class or id and rendering text or nested structures.

You can find more information about reconciliation on the official blog of one of the core React developers.

What is the purpose of using React Refs? Give an example of the problem you solved with React Refs.

React Refs create references to the element. This gives us access to a single element without the need for using `querySelector()`.

```

const App = () => {

const containerRef = React.useRef(null);

return <div ref={containerRef}>Hello</div>

}

```

They may have different usage. Most often it is the tree manipulation without React or work with an external library.

HTML / CSS / JS

What is the differences between an arrow and a normal function?

In the normal function this refers to the parent context, whereas the arrow function uses the so-called lexical scoping, which means this refers to the surrounding space. In fact, this is the main and the most important difference. What’s more, in the arrow function we cannot use, e.g. super and arguments. The easiest and at the same time the most common example is to use the parent context while passing the callback:

```

function timer() {

this.seconds = 0;

setInterval(function addSecond() {

this.seconds++; // Error, function addSecond() defines its own ‘this’ and doesn’t have access to ‘this’ function timer

}, 1000);

}

```

```

function timer() {

this.seconds = 0;

setInterval(() => {

this.seconds++; // Success, ‘this’ property refers to the context of timer function

}, 1000);

}

```

What should you pay attention to when taking care of the best animation performance and transitions in CSS?

Use will-change property. It allows you to “notify” a browser about the changes you’re going to perform on the element. In this way, the browser will be able to optimize/allocate resources before we set off an animation. It can be clearly illustrated by creating layers for 3D transformation before you actually need them. This results in smoother animation.

Assuming that you would like to use 3D transform on some element, add:

```

will-change: transform;

```

Remember to use it wisely — it’s very ‘resource-consuming’. This means that you shouldn’t use it as a remedy for all the problems and add to every animation. You had better treat it as the last resort in the fight against performance ;)

Unless the animation requirements state otherwise, you should use only the opacity and transform properties (position, scale, rotation). It’s caused by the fact that both properties do not perform layout operation. To notice the differences I recommend a video on YouTube.

And last but not least, do not animate everything at the same time! ;)

Explain the differences between synchronous and asynchronous code.

The synchronous code generally means that you can only do one thing at a time — something has to end for something else to start. The program is executed line by line, one line at a time.

Asynchronous means that you can do several things at the same time, and you don’t have to wait for them to be done to move on.

Soft

Give me the instructions on how to perform Code Review, based on your experience. Do you think it’s worth doing it? And if so, what are the benefits?

Code Review is a complex process and every developer can have their own recipe for success. This question can be an opening for a really interesting discussion. Here are our tips on how the Code Review process should look like. You can take advantage of the below points during your interview.

  • Code Review should be the discussion between developers. Sometimes the biggest challenge is to understand what someone had in mind. It refers both to the person who asks for checking PR and the programmer who is going to check given functionality.
  • Try to look through and understand the whole code. Then, read the detailed description of the task. Without the context it will be really difficult to understand what the author had in mind. Also, read the PR description and check if there are any questions or highlighted fragments that are uncertain for the developer.
  • It is important to convey the pros and cons of the solution. If you suggest anything else, explain in a few sentences why you think it would be better. People need to know why they are asked to make a change. Otherwise, they may feel criticized, which is not our aim. The exchange of information should always be constructive. The information exchange should always be constructive. ;)
  • Avoid sarcasm and jokes. It usually leads to misunderstandings, as not everybody can grasp your sense of humor.
  • Always answer every question/comment. Don’t let anyone feel ignored.
  • Don’t linger too long on questions! There is nothing worse than forcing people to wait a few days for comments/merging. By doing so, you’re holding them back from working on the code!
  • It is a good idea to prepare a checklist of things that need to be constantly verified, e.g.

-whether the tests are passing well,

-if the code is formatted properly,

-if the code is semantic and keeps the standards of the current code base,

-if appropriate error handling has been implemented,

-that the code is DRY,

-how ongoing changes affect the current code.

Ideally, most of these points should be automated.

Why do we conduct Code Reviews at all?

Currently, Code Review is the best method to ensure high code quality and minimize software errors. It guarantees the implementation of good practices within a given project. It checks the compatibility with the architecture and generally accepted standards. Not to mention the enormous educational values that it carries.

Undeniably, Code Review has the flaws, too. First of all, it is an extremely time-consuming process. In some situations it hinders developers from working on their own tasks. Anyway, when wisely planned and effectively conducted, it brings a lot of benefits.

Summing up

We believe this article brought you closer to the basics, plus gave you a deeper insights of a few more abstract issues, at least for some developers. We described the front-end topics, which hopefully you will find beneficial when preparing for an interview.

The set of questions selected by our team is not accidental. It is not only a revision of Front-end theory, but also a handful of useful tips, which will help you to verify your technical background and the direction you should follow in order to fully demonstrate your knowledge during the interview.

About the authors

Adrian Wolański

Having vast experience in graphic designing and a countless of ideas per minute, he is developing in the front-end field in Liki. While watching over the projects as a Team Leader, he passes his inborn enthusiasm on the rest of the team. He will eagerly dispel all your doubts concerning Angular.

Marcin Skrzyński

He’s a skillful FrontEnd Developer who’s spreading his wings in Liki. Driven by a constant crave for knowledge he’s seeking opportunities to expand his competence. You can meet him at tech conferences and meetups looking for tech inspiration. He will gladly involve in inspiring conversation regarding Frontend tidbits.

Michał Łyczko

A true tech enthusiast who isn’t afraid of hard work and is always in a good mood. He’s no stranger to Angular, RxJS, JavaScript and other Frontend technologies. Thanks to his technological flair, sharp mind and positive attitude he is able to solve any complex problem.

Krzysztof Wyrzykowski

He is a qualified programmer with extensive experience in creating interactive web and mobile applications. For over 10 years he has been fascinated by the world of Front-end. He loves working with different technologies, but specializes mainly in ReactJs and Django. As a CTO in Liki he always supports the whole team and willingly shares his knowledge. In his free time, he writes the tech articles on his blog.

--

--