Must know angular interview questions
20 JavaScript and 20 Angular concepts along with code snippets
JavaScript Concepts with Code and Explanation
Event Delegation
document.querySelector('#parent').addEventListener('click', function(event) { if (event.target && event.target.matches('button.classname')) { console.log('Button clicked!'); } });
Explanation: Event delegation is useful when attaching events to many elements. Here, the parent element listens for clicks, and if the clicked element matches the button with
classname
, the event handler is triggered.Asynchronous Operations
async function fetchData() { const result = await new Promise((resolve) => setTimeout(() => resolve('Data fetched!'), 1000)); console.log(result); } fetchData();
Explanation: This uses
async/await
to handle asynchronous code. ThePromise
is resolved after 1 second, andawait
pauses the execution until thePromise
resolves.Difference Between
==
and===
console.log(5 == '5'); // true console.log(5 === '5'); // false
Explanation:
==
compares values but performs type coercion, while===
compares both value and type, which is stricter.Closures
function outerFunction() { let outerVar = 'I am outer'; return function innerFunction() { console.log(outerVar); }; } const inner = outerFunction(); inner(); // Logs 'I am outer'
Explanation: A closure allows the inner function to access variables from its outer function even after the outer function has returned.
Higher-Order Functions
const numbers = [1, 2, 3, 4]; const doubled = numbers.map(num => num * 2); console.log(doubled); // [2, 4, 6, 8]
Explanation: Higher-order functions take other functions as arguments or return a function. Here,
map()
is a higher-order function that transforms each number.this
Contextconst person = { name: 'John', greet: function() { console.log(`Hello, ${this.name}`); } }; person.greet(); // 'Hello, John'
Explanation: The value of
this
refers to the objectperson
. Inside thegreet
method,this.name
accesses thename
property of theperson
object.Prototype Chain
function Person(name) { this.name = name; } Person.prototype.greet = function() { console.log(`Hello, ${this.name}`); }; const john = new Person('John'); john.greet(); // 'Hello, John'
Explanation: The prototype chain enables
Person
objects to share methods. The methodgreet
is added to thePerson.prototype
, allowing instances to access it.Arrow Functions
const numbers = [1, 2, 3]; const squares = numbers.map(n => n * n); console.log(squares); // [1, 4, 9]
Explanation: Arrow functions provide a more concise syntax and do not have their own
this
binding, making them ideal for short functions.call
,apply
, andbind
function greet() { console.log(`Hello, ${this.name}`); } const person = { name: 'John' }; greet.call(person); // 'Hello, John' greet.apply(person); // 'Hello, John' const boundGreet = greet.bind(person); boundGreet(); // 'Hello, John'
Explanation:
call()
andapply()
invoke the function immediately, setting thethis
value.bind()
returns a new function withthis
bound toperson
.Modules in JavaScript In
module1.js
:
export function greet() {
console.log('Hello');
}
In main.js
:
import { greet } from './module1.js';
greet(); // 'Hello'
Explanation: Modules allow splitting code into reusable pieces. You can export functions or variables from one file and import them into another.
- Hoisting
console.log(x); // undefined
var x = 5;
Explanation: Variables declared with var
are hoisted to the top, meaning they can be used before their declaration, but their value will be undefined
.
- Promises
const myPromise = new Promise((resolve, reject) => {
setTimeout(() => resolve('Done!'), 1000);
});
myPromise.then(result => console.log(result)); // 'Done!'
Explanation: A Promise
is an object representing the eventual completion of an asynchronous operation. The then()
method handles the resolved value.
- Difference Between
var
,let
, andconst
var x = 10; // function-scoped, can be re-assigned
let y = 20; // block-scoped, can be re-assigned
const z = 30; // block-scoped, cannot be re-assigned
Explanation: var
is function-scoped and can be redeclared. let
and const
are block-scoped, with const
being immutable after assignment.
- Immediately Invoked Function Expression (IIFE)
(function() {
console.log('IIFE executed');
})();
Explanation: IIFE is a function that runs as soon as it’s defined. It helps create a private scope and avoid polluting the global namespace.
reduce()
const numbers = [1, 2, 3, 4];
const sum = numbers.reduce((acc, curr) => acc + curr, 0);
console.log(sum); // 10
Explanation: The reduce()
method applies a function to an accumulator and each element of the array, reducing the array to a single value.
async
/await
async function fetchData() {
const result = await new Promise(resolve => setTimeout(() => resolve('Data!'), 1000));
console.log(result);
}
fetchData();
Explanation: The async
keyword marks a function as asynchronous, and await
is used to wait for the Promise
to resolve. This simplifies working with asynchronous code.
- Default Parameters
function greet(name = 'Guest') {
console.log(`Hello, ${name}`);
}
greet(); // 'Hello, Guest'
Explanation: Default parameters allow setting a default value for function arguments. If no argument is provided, the default value is used.
- Destructuring
const person = { name: 'John', age: 25 };
const { name, age } = person;
console.log(name, age); // 'John', 25
Explanation: Destructuring allows extracting values from objects or arrays and assigning them to variables in a concise way.
- Template Literals
const name = 'John';
console.log(`Hello, ${name}`); // 'Hello, John'
Explanation: Template literals use backticks to embed expressions and create multi-line strings. They replace the older +
string concatenation method.
- Error Handling with
try...catch
try {
throw new Error('Something went wrong');
} catch (error) {
console.log(error.message); // 'Something went wrong'
}
Explanation: The try...catch
block handles exceptions. If an error is thrown in the try
block, it is caught in the catch
block, preventing the application from crashing.
Angular Concepts with Code and Explanation
Component in Angular
@Component({ selector: 'app-root', template: `<h1>Hello, {{name}}</h1>`, }) export class AppComponent { name = 'Angular'; }
Explanation: A component is the building block of Angular applications. It controls a portion of the UI and the logic behind it, defined with a
template
.Component Lifecycle
@Component({ selector: 'app-example', template: `<p>Example Component</p>`, }) export class ExampleComponent implements OnInit { ngOnInit() { console.log('Component initialized'); } }
Explanation: The
OnInit
lifecycle hook runs after the component is created. It is often used to initialize data or make API calls.Dependency Injection
```ts @Injectable({ providedIn: 'root' })
export class DataService { getData() { return 'Data from service'; } }
@Component({
selector: 'app-root',
template: <p>{{data}}</p>
,
})
export class AppComponent {
data: string;
constructor(private dataService: DataService) {
this.data = this.dataService.getData();
}
}
**Explanation**: Angular uses dependency injection to provide services to components. The `DataService` is injected into the `AppComponent` and used to retrieve data.
4. **Routing in Angular**
```ts
const routes: Routes = [
{ path: '', component: HomeComponent },
{ path: 'about', component: AboutComponent }
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
Explanation: Angular’s RouterModule
allows navigation between different views (components) by mapping URL paths to components.
Services in Angular
@Injectable({ providedIn: 'root' }) export class LoggingService { log(message: string) { console.log(`Log: ${message}`); } } @Component({ selector: 'app-root', template: `<p>Check the console</p>`, }) export class AppComponent { constructor(private loggingService: LoggingService) { this.loggingService.log('Component loaded'); } }
Explanation: Services provide reusable logic that can be shared across components. In this example,
LoggingService
logs messages to the console.Two-Way Data Binding
@Component({ selector: 'app-root', template: `<input [(ngModel)]="name"><p>Hello, {{name}}</p>`, }) export class AppComponent { name = ''; }
Explanation: Two-way data binding allows synchronization between the UI and the component’s data. Any changes in the input will reflect in the
name
property and vice versa.Structural Directives (
ngIf
,ngFor
)<div *ngIf="isVisible">This is visible</div> <ul> <li *ngFor="let item of items">{{ item }}</li> </ul>
Explanation: Structural directives like
*ngIf
and*ngFor
are used to conditionally add or remove elements and loop through lists in the template.Reactive Forms in Angular
@Component({ selector: 'app-form', template: ` <form [formGroup]="form"> <input formControlName="name"> </form> `, }) export class FormComponent implements OnInit { form: FormGroup; constructor(private fb: FormBuilder) {} ngOnInit() { this.form = this.fb.group({ name: [''] }); } }
Explanation: Reactive forms provide more flexibility and control than template-driven forms. Form controls and groups are explicitly created in the component class.
Template-Driven Forms
@Component({ selector: 'app-form', template: ` <form #form="ngForm"> <input [(ngModel)]="name" name="name" required> </form> `, }) export class FormComponent { name = ''; }
Explanation: Template-driven forms rely on directives like
ngModel
in the template to manage the form state. It's simpler but less flexible than reactive forms.Pipes in Angular
@Component({
selector: 'app-root',
template: `<p>{{ today | date:'fullDate' }}</p>`,
})
export class AppComponent {
today = new Date();
}
Explanation: Pipes transform data in the template. The date
pipe formats dates, but there are many other built-in and custom pipes that can be used.
- Custom Directives
@Directive({
selector: '[appHighlight]'
})
export class HighlightDirective {
@HostBinding('style.backgroundColor') bgColor = 'yellow';
}
// Usage in template: <p appHighlight>Highlighted text</p>
Explanation: Directives are used to modify the behavior or appearance of elements. This custom directive changes the background color to yellow.
- Event Binding
@Component({
selector: 'app-root',
template: `<button (click)="onClick()">Click me</button>`,
})
export class AppComponent {
onClick() {
console.log('Button clicked!');
}
}
Explanation: Event binding connects DOM events (like click
) to methods in the component, allowing interaction between the template and the component logic.
- Route Guards
@Injectable({ providedIn: 'root' })
export class AuthGuard implements CanActivate {
canActivate(): boolean {
return true; // Logic to check if route can be accessed
}
}
const routes: Routes = [
{ path: 'dashboard', component: DashboardComponent, canActivate: [AuthGuard] }
];
Explanation: Route guards prevent access to certain routes based on custom logic. For example, you can block unauthorized users from accessing the dashboard.
- Handling HTTP Requests
import { HttpClient } from '@angular/common/http';
@Component({
selector: 'app-root',
template: `<p>{{ data }}</p>`,
})
export class AppComponent {
data: any;
constructor(private http: HttpClient) {
this.http.get('https://api.example.com/data').subscribe(result => {
this.data = result;
});
}
}
Explanation: Angular's HttpClient
service is used to make HTTP requests. The data fetched from the API is displayed in the template.
- Change Detection
@Component({
selector: 'app-root',
changeDetection: ChangeDetectionStrategy.OnPush,
template: `<p>{{ data }}</p>`,
})
export class AppComponent {
@Input() data!: string;
}
Explanation: Change detection checks if any data in the component has changed. The OnPush
strategy only checks for changes when the @Input()
value changes.
ngOnChanges
Lifecycle Hook
@Component({
selector: 'app-child',
template: `<p>{{ data }}</p>`,
})
export class ChildComponent implements OnChanges {
@Input() data!: string;
ngOnChanges(changes: SimpleChanges) {
console.log('Data changed:', changes);
}
}
Explanation: The ngOnChanges
hook is triggered whenever input properties change, allowing you to react to these changes.
- Custom Pipes
@Pipe({ name: 'capitalize' })
export class CapitalizePipe implements PipeTransform {
transform(value: string): string {
return value.charAt(0).toUpperCase() + value.slice(1);
}
}
// Usage in template: {{ 'angular' | capitalize }} <!-- Output: Angular -->
Explanation: Custom pipes transform data in the template. This pipe capitalizes the first letter of a string.
- Content Projection
<!-- Parent component -->
<app-child>
<p>Projected content</p>
</app-child>
<!-- Child component -->
<ng-content></ng-content>
Explanation: Content projection allows you to project content from a parent component into a child component using <ng-content>
.
- Using
ngFor
<ul>
<li *ngFor="let item of items">{{ item }}</li>
</ul>
Explanation: ngFor
is a structural directive that iterates over an array and renders a list of elements dynamically.
- HTTP Error Handling
this.http.get('https://api.example.com/data').pipe(
catchError(error => {
console.error('Error occurred:', error);
return throwError(() => new Error('Something went wrong'));
})
).subscribe(data => console.log(data));
Explanation: When making HTTP requests, it's important to handle errors. The catchError
operator allows you to catch and handle errors in a stream of data.
These explanations, along with code examples, provide a solid understanding of key JavaScript and Angular concepts that every front-end Angular developer should master.
Subscribe to my newsletter
Read articles from Indrajeet Giram directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Indrajeet Giram
Indrajeet Giram
Hello there! My name is Indrajeet, and I'm an intermediate web👩🏻💻 developer. I'm writing to share my programming views🤨 and hope my writeups will be helpful in your 😀 web development journey.