Skip to main content

Decorators and forwarding, call/apply

Advanced-JS Functions: Call and Apply



What is the primary distinction between the JavaScript methods call and apply?

View Answer:
Interview Response: The primary difference between call and apply is how arguments are passed to the function being called: call uses comma-separated arguments, while apply uses an array.

Code Example:

let pokemon = {
firstname: 'Pika',
lastname: 'Chu ',
getPokeName: function () {
let fullname = this.firstname + ' ' + this.lastname;
return fullname;
},
};

let pokemonName = function (snack, hobby) {
console.log(this.getPokeName() + ' loves ' + snack + ' and ' + hobby);
};

// Call Method
pokemonName.call(pokemon, 'sushi', 'algorithms');
// returns Pika Chu loves sushi and algorithms

// Apply Method
pokemonName.apply(pokemon, ['sushi', 'algorithms']);
// returns Pika Chu loves sushi and algorithms

Can you explain how transparent caching works in JavaScript?

View Answer:
Interview Response: Transparent caching in JavaScript is the automatic storage and retrieval of resources in the browser cache. It improves website performance by reducing network requests and page load times, without requiring additional code from the developer.

Technical Response: When are CPU-heavy functions return the same result consistently. You can use transparent caching to reduce the user's browser or server load by implementing a decorator. The decorator handles the function's result to determine if the result gets cached or not. Transparent caching also reduces the bandwidth necessary to perform tasks and can significantly improve application performance. One of the main benefits of creating decorators is the ability to re-use cached results.

Code Example:

function slow(x) {
// there can be a heavy CPU-intensive job here
console.log(`Called with ${x}`);
return x;
}

function cachingDecorator(func) {
let cache = new Map();

return function (x) {
if (cache.has(x)) {
// if there's such key in cache
return cache.get(x); // read the result from it
}

let result = func(x); // otherwise call func

cache.set(x, result); // and cache (remember) the result
return result;
};
}

slow = cachingDecorator(slow);

console.log(slow(1)); // slow(1) is cached and the result returned
console.log('Again: ' + slow(1)); // slow(1) result returned from cache

console.log(slow(2)); // slow(2) is cached and the result returned
console.log('Again: ' + slow(2)); // slow(2) result returned from cache

Can you explain what a decorator is in JavaScript?

View Answer:
Interview Response: In JavaScript, a decorator is a design pattern that allows behavior to be added to an individual object or class without changing the object or class itself.

Technical Response: A decorator is a function that modifies the function's behavior or method passed to it by returning a new function. You can implement decorators in any language that supports functions as first-class citizens. You can bind a function to a variable or pass it as an argument to another function.

Code Example:

function doSomething(name) {
console.log('Hello, ' + name);
}

function loggingDecorator(wrapped) {
// Decorator
return function () {
console.log('Starting');
const result = wrapped.apply(this, arguments);
console.log('Finished');
return result;
};
}

const wrapped = loggingDecorator(doSomething);

doSomething('Graham');
// Hello, Graham

wrapped('Graham');
// Starting
// Hello, Graham
// Finished

Can you explain the function of the call() method in JavaScript?

View Answer:
Interview Response: The call() method in JavaScript invokes a function with a specific "this" value and arguments provided individually. It essentially calls a function and sets the "this" keyword to the first argument passed to the method, with subsequent arguments passed as comma-separated values.

Technical Response: The call() method allows for a function/method belonging to one object to be assigned and called for a different object. The call() method provides a new " this " value to the function/method. You can use the "call" method to write a method once and then inherit it in another object without having to rewrite the method for the new object. The call method expects a list of parameters, whereas the apply method expects an array of arguments.

Code Example:

Syntax: func.call([thisArg[, arg1, arg2, ...argN]]);

function Person(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
this.getFullName = function () {
return `${this.firstName} ${this.lastName}`;
};
}

function Man(firstName, lastName) {
Person.call(this, firstName, lastName); // calling Person firstName, lastName
this.gender = 'Man';
}

const eric = new Man('Eric', 'Wilson');
console.log(eric.firstName + ' ' + eric.lastName); // returns Eric + Wilson

console.log(eric.getFullName()); // method call returns Full Name: Eric Wilson

Can you explain the function of the apply() method?

View Answer:
Interview Response:The apply() method in JavaScript is a way to invoke a function and set its "this" keyword explicitly to a specified object, with arguments provided as an array or array-like object.

Code Example:

Syntax: func.apply(thisArg, [ argsArray]);

let customer1 = { name: 'Leo', email: 'leo@gmail.com' };
let customer2 = { name: 'Nat', email: 'nat@hotmail.com' };

function greeting(text, text2) {
console.log(`${text} ${this.name}, ${text2}`);
}

greeting.apply(customer1, ['Hello', 'How are you?']);
// output Hello Leo, How are you?

greeting.apply(customer2, ['Hello', 'How are you?']);
// output Hello Nat How are you?

How does method borrowing work in JavaScript?

View Answer:
Interview Response: Method borrowing in JavaScript is a technique that allows an object to borrow methods from another object's prototype chain using the call() or apply() method, allowing for code reuse and avoiding duplication.

Code Example:

let bird = {
name: 'Lark',
do: function (greet) {
console.log('I am a ' + this.name + ', I ' + greet + '!');
},
};

bird.do('tweet');

let butterFly = {
name: 'Swallowtail',
};

bird.do.call(butterFly, 'flutter'); // Borrowing the do method from bird

// Returns:
// I am a Lark, I tweet!
// I am a Swallowtail, I flutter!

How do you use the call() method to invoke a function with a specific "this" value?

View Answer:
Interview Response: You can use the call() method by passing the object you want to set as the "this" value as the first argument, followed by the function arguments as comma-separated values.

Code Example:

let obj = {value: 10};

function multiply(n) {
return this.value * n;
}

console.log(multiply.call(obj, 5)); // Output: 50

Can you explain how to borrow methods from another object using the call() method?

View Answer:
Interview Response: Borrowing methods involves using call() to invoke a method from another object, with this set to your object, allowing the borrowed method to operate on your object.

Code Example:

let dog = {
name: "Rover",
sound: "Woof",
makeSound: function() {
console.log(this.sound);
}
};

let cat = {
name: "Whiskers",
sound: "Meow"
};

// Borrowing the makeSound method from dog
dog.makeSound.call(cat); // Output: Meow

What happens if you pass null or undefined as the first argument to the call() method?

View Answer:
Interview Response: If null or undefined is passed as the first argument to call(), JavaScript treats "this" as the global object in non-strict mode, or undefined in strict mode.

Code Example:

function greet() {
console.log(this.message);
}

// Define a global variable
message = "Hello, World!";

// Call greet with null as the first argument
greet.call(null); // Output: "Hello, World!" in non-strict mode

// Now in strict mode
"use strict";
function greetStrict() {
console.log(this.message);
}

greetStrict.call(null); // Throws TypeError: Cannot read properties of null (reading 'message') in strict mode

How do you use the apply() method to invoke a function with a specific "this" value and arguments provided as an array?

View Answer:
Interview Response: To invoke a function with a specific "this" value and arguments as an array, use the apply() method, passing "this" value as the first argument and the array as the second.

Code Example:

let obj = {value: 10};

function multiply(n1, n2) {
return this.value * n1 * n2;
}

console.log(multiply.apply(obj, [5, 2])); // Output: 100

Can you explain how to borrow methods from another object using the apply() method?

View Answer:
Interview Response: Borrowing methods with apply() involves invoking a method from another object with this set to your object and an array of arguments, allowing operation on your object.

Code Example:

let dog = {
name: "Rover",
sound: "Woof",
makeSound: function(times) {
while(times--)
console.log(this.sound);
}
};

let cat = {
name: "Whiskers",
sound: "Meow"
};

// Borrowing the makeSound method from dog
dog.makeSound.apply(cat, [3]); // Output: Meow, Meow, Meow