JavaScript Interview Coding Questions — 4
Continuing to questions… As I said in first blog, these are generally evaluation based code snippets.
- This one is about scope differences of Arrow & Regular function definitions.
// 1. What will be logged? Why?const module1 = { x: 55, getX: function () { console.log('x:', this.x); }};const module2 = { x: 55, getX: () => { console.log('x:', this.x); }};(function() { this.x = 66; module1.getX(); module2.getX();})();
The console output will be following:
x: 55
x: 66
Because this
refers to wrapper object in regular function so this.x
logs x
property of wrapper module1
object in first example. On the other side, arrow functions don’t bind their own scope, but inherit it from the parent one, which is window
or the global
object in this case.
You can test it via this link.
2. Let’s examine same issue in a different example.
// 2. What will be logged? Why?const message1 = { hello : 'Hello', names : ['Sue', 'Joe'], showMessage: function () { this.names.forEach(function(name) { console.log(`${this.hello} ${name}`); }); }}message1.showMessage();const message2 = { hello : 'Hello', names : ['Sue', 'Joe'], showMessage: function () { this.names.forEach(name => { console.log(`${this.hello} ${name}`); }); }}message2.showMessage();
The console output will be following:
undefined Sue
undefined Joe
Hello Sue
Hello Joe
In message1
, the function inside this.names.forEach
is defined as regular function, so this
equals to global object by default (Window
in browsers, global
in Node.js) and it has no hello
property. this
equals to undefined
by default in strict mode!
On the other hand, in message2
, the function inside this.names.forEach
is defined as arrow function. Arrow functions don’t have own scope, so it equals to owner’s (which is showMessage
in this case) scope. The scope of showMessage
is the wrapper object message2
. For this reason, we can reach hello
property of message2
by using this.hello
.
You can test it via this link.
3. This question is to evaluate knowledge about promises in JavaScript.
const promiser = ms => new Promise((resolve, reject) => { setTimeout(() => { resolve('wait wait..') }, ms)});const timeout = new Promise((resolve, reject) => { setTimeout(() => { resolve('timeout!') }, 2000)});const race1 = Promise.race([promiser(1000), timeout]);const race2 = Promise.race([promiser(3000), timeout]);// What will be the output?race1.then(res => console.log('race1:', res)) .catch(err => console.log('race1:', err));// What will be the output?race2.then(res => console.log('race2:', res)) .catch(err => console.log('race2:', err));
The result will be below:
race1: wait wait..
race2: timeout!
Promise.race()
returns a winner promise which fulfills or rejects sooner. Our timeout
promise is resolved in 2 seconds. The promiser
is taking resolving time as parameter. In first race, it resolved in 1 second so wins the race, but in the second race it takes 3 seconds as parameter so timeout
is resolved earlier.
You can test it via this link.
You can read the previous articles of this series from the links below: