ES6 Interview Questions - BEHIND JAVA

ES6 Interview Questions

Share This

1. What is ES6?

ES6 refers to version 6 of the ECMA Script programming language. ECMA Script is the standardized name for JavaScript, and version 6 is the next version after version 5, which was released in 2011. It is a major enhancement to the JavaScript language, and adds many more features intended to make large-scale software development easier.

ECMAScript, or ES6, was published in June 2015. It was subsequently renamed to ECMAScript 2015. Web browser support for the full language is not yet complete, though major portions are supported. Major web browsers support some features of ES6. However, it is possible to use software known as a transpiler to convert ES6 code into ES5, which is better supported on most browsers.

2. What are the Key features of ES6?

  • Support for constants (also known as “immutable variables”)
  • Block-Scope support for both variables, constants, functions
  • Arrow Functions
  • Extended Parameter Handling
  • Template Literals
  • Extended Literals
  • Enhanced Regular Expression
  • Enhanced Object Properties
  • Destructuring Assignment
  • Modules, Classes, Iterators, Generators
  • Support for Map/Set & WeakMap/WeakSet
  • Promises, Meta-Programming ,Internationalization & Localization

The remaining questions are based on these key features

3. What are constants in ES6?

ES6 introduced block-scoped constructs to JavaScript and one of them is constants. A block-scope exists between an enclosing curly brace. A declaration with the keyword const creates a constant.

When a variable is declared with const, its name becomes reserved and you would not be able to declare another variable with the same name with any other declaration constructs like var or let in the same scope.

const my_var = 7;

// would fail because my_var is already a reserved name
var my_var = 'cat'; 
let my_var = 'cat'; 

4. Explain about Scope in ES6?

var — function scope

a variable being declared using var will be function scoped, meaning it will exist within the scope of the function it’s declared inside of.

function myFunc() {  
  var name = 'Luke'
  console.log(name); // 'Luke'
}

myFunc();

console.log(name); // name is not defined  

other types of blocks — like if-statements, loops etc — will not be considered as a scope.

if(true) {  
  var name = 'Luke'
}

console.log(name); // 'Luke'  

Using var, the variable name is available outside the if-statement it was declared inside of. This is because they're in the same scope.

let and const — the introduction of block scope

In ES6, let and const were introduced as alternative ways of declaring variables — both being blocked scoped. In block scope, any block will be a scope. This will give a more consistent behaviour.

if(true) {  
  let name = 'Luke'
}

console.log(name); // name is not defined  

5. When function scope get confusing?

Having a local variable inside a scope with the same name as a variable in the outer scope is perfectly fine.

var name = 'Luke';
const func = () => {  
  var name = 'Phil';
  console.log(name); // 'Phil'
}

func();

console.log(name); // 'Luke'  

name in the outer scope keeps the initial declaration value ‘Luke’ even after func — containing an equally named local variable — has been executed.

The problem however is that since function scope only covers functions and not other types of blocks, we would get a quite different behavior with other blocks.

var name = 'Luke';

if (true) {  
  var name = 'Phil';
  console.log(name); // 'Phil'
}

console.log(name); // 'Phil'  

In this scenario ‘Phil’ will be printed in both places. This is because both variables are in the same scope, resulting in ‘Phil’ overriding the first variable declaration.

6. How to declare an arrow function?

Arrow functions make our code more concise, and simplify function scoping and the this keyword. By using arrow functions, we avoid having to type the function keyword, return keyword (it’s implicit in arrow functions), and curly brackets.

Here follows the different types of arrow functions

// (param1, param2, paramN) => expression

// ES5
var multiplyES5 = function(x, y) {
  return x * y;
};

// ES6
const multiplyES6 = (x, y) => { return x * y };


//ES5
var docLogEs5 = function docLog() {
    console.log(document);
};

//ES6
var docLogEs6 = () => { console.log(document); };
docLogEs6(); // #document... <html> ….



//ES5
var phraseSplitterEs5 = function phraseSplitter(phrase) {
  return phrase.split(' ');
};

//ES6
const phraseSplitterEs6 = phrase => phrase.split(" ");

console.log(phraseSplitterEs6("ES6 Awesomeness"));  // ["ES6", "Awesomeness"]


//ES5
var setNameIdsEs5 = function setNameIds(id, name) {
  return {
    id: id,
    name: name
  };
};

// ES6
var setNameIdsEs6 = (id, name) => ({ id: id, name: name });

console.log(setNameIdsEs6 (4, "Kyle"));   // Object {id: 4, name: "Kyle"}

One common use case for arrow functions is array manipulation and the like. It’s common that you’ll need to map or reduce an array.

const smartPhones = [
  { name:'iphone', price:649 },
  { name:'Galaxy S6', price:576 },
  { name:'Galaxy Note 5', price:489 }
];

// ES5
var prices = smartPhones.map(function(smartPhone) {
  return smartPhone.price;
});

console.log(prices); // [649, 576, 489]

// ES6
const prices = smartPhones.map(smartPhone => smartPhone.price);
console.log(prices); // [649, 576, 489]

Promises and Callbacks?

Code that makes use of asynchronous callbacks or promises often contains a great deal of function and return keywords. When using promises, these function expressions will be used for chaining.

// ES5
aAsync().then(function() {
  returnbAsync();
}).then(function() {
  returncAsync();
}).done(function() {
  finish();
});

// ES6
aAsync().then(() => bAsync()).then(() => cAsync()).done(() => finish);

7. what are the benefits of arrow functions?

Scope safety: When arrow functions are used consistently, everything is guaranteed to use the same thisObject as the root. If even a single standard function callback is mixed in with a bunch of arrow functions there's a chance the scope will become messed up.

Compactness: Arrow functions are easier to read and write. (This may seem opinionated so I will give a few examples further on).

Clarity: When almost everything is an arrow function, any regular function immediately sticks out for defining the scope. A developer can always look up the next-higher function statement to see what the thisObject is.

8. what are the extended parameter handling in es6?

default

ES6 gives us a way to set default function parameters. Any parameters with a default value are considered to be optional.

function inc(number, increment = 1) {
  return number + increment;
}
console.log(inc(2, 2)); // 4
console.log(inc(2));    // 3

also able to set default values to parameters that appear before arguments without default values:

function sum(a, b = 2, c) {
  return a + b + c;
}
console.log(sum(1, 5, 10));         // 16 -> b === 5
console.log(sum(1, undefined, 10)); // 13 -> b as default

rest

Rest parameters are indicated by three dots … preceding a parameter. Named parameter becomes an array which contain the rest of the parameters.

function sum(…numbers) {
  var result = 0;
  numbers.forEach(function (number) {
    result += number;
  });
  return result;
}
console.log(sum(1)); // 1
console.log(sum(1, 2, 3, 4, 5)); // 15

Restriction: no other named arguments can follow in the function declaration.

function sum(…numbers, last) { // causes a syntax error
  var result = 0;
  numbers.forEach(function (number) {
    result += number;
  });
  return result;
}

spread

The spread is closely related to rest parameters, because of … (three dots) notation. It allows to split an array to single arguments which are passed to the function as separate arguments.

function sum(a, b, c) {
  return a + b + c;
}
var args = [1, 2, 3];
console.log(sum(…args)); // 6

9. Explain about Template Literals?

Template literals are enclosed by the back-tick (` `) character instead of double or single quotes. Template literals can contain placeholders. These are indicated by the dollar sign and curly braces (${expression}). The expressions in the placeholders and the text between them get passed to a function. The default function just concatenates the parts into a single string. If there is an expression preceding the template literal (tag here), this is called a "tagged template".

Here follows a coding comparison of template literals

//Multi-line strings
//using normal string
console.log('string text line 1\n' +
'string text line 2');
// "string text line 1
// string text line 2"

//using template literals

console.log(`string text line 1
string text line 2`);
// "string text line 1
// string text line 2"


//Expression interpolation

//using normal string
var a = 5;
var b = 10;
console.log('Fifteen is ' + (a + b) + ' and\nnot ' + (2 * a + b) + '.');
// "Fifteen is 15 and
// not 20."


//using template literals
var a = 5;
var b = 10;
console.log(`Fifteen is ${a + b} and
not ${2 * a + b}.`);
// "Fifteen is 15 and
// not 20."


//Nesting templates
//using normal string
var classes = 'header'
classes += (isLargeScreen() ?
   '' : item.isCollapsed ?
     ' icon-expander' : ' icon-collapser');
  
//using template literals
const classes = `header ${ isLargeScreen() ? '' :
    (item.isCollapsed ? 'icon-expander' : 'icon-collapser') }`;

Tagged templates

A more advanced form of template literals are tagged templates. Tags allow you to parse template literals with a function. The first argument of a tag function contains an array of string values. The remaining arguments are related to the expressions. In the end, your function can return your manipulated string (or it can return something completely different as described in the next example). The name of the function used for the tag can be whatever you want.

var person = 'Mike';
var age = 28;

function myTag(strings, personExp, ageExp) {
  var str0 = strings[0]; // "That "
  var str1 = strings[1]; // " is a "

  // There is technically a string after
  // the final expression (in our example),
  // but it is empty (""), so disregard.
  // var str2 = strings[2];

  var ageStr;
  if (ageExp > 99){
    ageStr = 'centenarian';
  } else {
    ageStr = 'youngster';
  }

  // We can even return a string built using a template literal
  return `${str0}${personExp}${str1}${ageStr}`;
}

var output = myTag`That ${ person } is a ${ age }`;

console.log(output);
// That Mike is a youngster
Tag functions don't need to return a string, as shown in the following example.

function template(strings, ...keys) {
  return (function(...values) {
    var dict = values[values.length - 1] || {};
    var result = [strings[0]];
    keys.forEach(function(key, i) {
      var value = Number.isInteger(key) ? values[key] : dict[key];
      result.push(value, strings[i + 1]);
    });
    return result.join('');
  });
}

var t1Closure = template`${0}${1}${0}!`;
t1Closure('Y', 'A');  // "YAY!"
var t2Closure = template`${0} ${'foo'}!`;
t2Closure('Hello', {foo: 'World'});  // "Hello World!"

10. Explain about extended literals?

Extended Object Literals simplify object creation and composition by reducing the required amount of typing with some syntactic sugar.

With this, object literals are now syntactically similar to ES6’s new class syntax and have less duplication in common use-cases like constructor function.

// The following two declarations are equivalent:
var es5 = {a: a, b: b, c: c};
var es6 = {a, b, c}; // Property name is inferred from variable name

11. Explain about Modules in ES6? What are the benefits of it?

A module is nothing more than a chunk of JavaScript code written in a file. The functions or variables in a module are not available for use, unless the module file exports them.

Modules allow you to, among other things, (a) split your code it into multiple, role-specific files (which makes maintenance easier when compared with managing all of your code in one monolithic file), (b) reuse code for multiple applications without literally copying that code from application to application, and (c) automatically load the code you need (i.e., dependencies) based on what the code itself requires rather than manually specifying each file to load (and in which order to load it) via, for example, script tags.

javaScript already has two popular, version-independent module formats: CommonJS (CJS) and Asynchronous Module Definition (AMD). Node.js uses CJS, which is great for server-side code, but not entirely appropriate for browser-side code because it assumes that there is direct, synchronous access to a file system. AMD shares many traits with CJS, including the ability to wrap (and therefore to use) CJS modules, but it is designed from the ground-up to be asynchronous. There are other module formats out there, but these are by far the most popular.

ES6 import and export statements standardize module syntax and semantics. Unlike CJS and AMD functions, these statements are built-in (making keywords out of what were once reserved words). Sometime in the distant future, that means that your users won’t have to download any extra code in order for you to write modular JavaScript. And in combination with advances like HTTP2, it may mean that you can use a lighter-weight build process and finer-grained client-side caching, which will improve the way you roll out fixes and updates to your end-users.

12. Explain about different types of list iterations?

for statement

for (var i = 0; i < selectObject.options.length; i++) {
    if (selectObject.options[i].selected) {
      numberSelected++;
    }
  }
  

do...while statement

var i = 0;
do {
  i += 1;
  console.log(i);
} while (i < 5);

while statement
var n = 0;
var x = 0;
while (n < 3) {
  n++;
  x += n;
}

labeled statement

markLoop:
while (theMark == true) {
   doSomething();
}

break statement

var x = 0;
var z = 0;
labelCancelLoops: while (true) {
  console.log('Outer loops: ' + x);
  x += 1;
  z = 1;
  while (true) {
    console.log('Inner loops: ' + z);
    z += 1;
    if (z === 10 && x === 10) {
      break labelCancelLoops;
    } else if (z === 10) {
      break;
    }
  }
}

continue statement

var i = 0;
var n = 0;
while (i < 5) {
  i++;
  if (i == 3) {
    continue;
  }
  n += i;
  console.log(n);
}
//1,3,7,12


var i = 0; 
var n = 0; 
while (i < 5) { 
  i++; 
  if (i == 3) { 
     // continue; 
  } 
  n += i; 
  console.log(n);
}
// 1,3,6,10,15

for...in statement and for...of statement

var arr = [3, 5, 7];
arr.foo = 'hello';

for (var i in arr) {
   console.log(i); // logs "0", "1", "2", "foo"
}

for (var i of arr) {
   console.log(i); // logs 3, 5, 7
}

13. What are different types of generators in ES6?

Generators are functions that can be paused and resumed, which enables a variety of applications.

As a first example, consider the following generator function whose name is genFunc:

function* genFunc() {
    console.log('First');
    yield; // (A)
    console.log('Second'); // (B)
}

Two things distinguish genFunc from a normal function declaration:

  1. It starts with the “keyword” function*.
  2. It is paused in the middle via yield.

Calling genFunc does not execute it. Instead, it returns a so-called generator object that lets us control genFunc’s execution:

let genObj = genFunc();

genFunc() is initially suspended at the beginning of its body. The method genObj.next() continues the execution of genFunc, until the next yield:

> genObj.next()
First
{ value: undefined, done: false }

As you can see in the last line, genObj.next() also returns an object. Let’s ignore that for now. It will matter once we look at generators as iterators.

genFunc is now paused in line (A). If we call next() again, execution resumes and line (B) is executed:

> genObj.next()
Second
{ value: undefined, done: true }

Afterwards, the function is finished, execution has left the body and further calls of genObj.next() have no effect.

Ways of creating generators

1. Via a generator function declaration:

function* genFunc() { ··· }
let genObj = genFunc();

2. Via a generator function expression:

const genFunc = function* () { ··· };
let genObj = genFunc();

3. Via a generator method definition in an object literal:

let obj = {
    * generatorMethod() {
        ···
    }
};
let genObj = obj.generatorMethod();

4. Via a generator method definition in a class definition (which can be a class declaration or a class expression [2]):

class MyClass {
    * generatorMethod() {
        ···
    }
}
let myInst = new MyClass();
let genObj = myInst.generatorMethod();

14. How to initialize map and set?

Map

Maps are a store for key / value pairs. Key and value could be a primitives or object references.

Let’s create a map:

let map = new Map(),
    val2 = 'val2',
    val3 = {
      key: 'value'
    };
map.set(0, 'val1');
map.set('1', val2);
map.set({ key: 2 }, val3);
console.log(map); // Map {0 => 'val1', '1' => 'val2', Object {key: 2} => Object {key: 'value'}}
console.log(map.get('1'))//val2

We can also use a couple of methods to iterate:

  • entries()-get all entries
  • keys()-get only all keys
  • values()-get only all values

Set

It’s a collection for unique values. The values could be also a primitives or object references.

let set = new Set();
set.add(1);
set.add('1');
set.add({ key: 'value' });
console.log(set); // Set {1, '1', Object {key: 'value'}}

Explain Weak Map and Weak Set?

WeakMap

WeakMaps provides leak-free object keyed side tables. It’s a Map that doesn’t prevent its keys from being garbage-collected. We don’t have to worry about memory leaks.

If the object is destroyed, the garbage collector removes an entry from the WeakMap and frees memory. It has almost the same API like a Map, but we can’t iterate over the WeakMap collection. We can’t even determine the length of the collection because we don’t have size attribute here.

The API looks like this:

new WeakMap([iterable])
WeakMap.prototype.get(key)        : any
WeakMap.prototype.set(key, value) : this
WeakMap.prototype.has(key)        : boolean
WeakMap.prototype.delete(key)     : boolean

WeakSet

Like a WeakMap, WeakSet is a Seat that doesn’t prevent its values from being garbage-collected. It has simpler API than WeakMap, because has only three methods:

WeakSet collection can‘t be iterated and we cannot determine its size.

new WeakSet([iterable])
WeakSet.prototype.add(value)    : any
WeakSet.prototype.has(value)    : boolean
WeakSet.prototype.delete(value) : boolean

15. Explain typed arrays?

Typed Arrays (Uint8Array, Int16Array, Float32Array, etc.) interpret the ArrayBuffer as an indexed sequence of elements of a single type.

Instances of DataView let you access data as elements of several types (Uint8, Int16, Float32, etc.), at any byte offset inside an ArrayBuffer.

The following browser APIs support Typed Arrays (details are mentioned later):

  • File API
  • XMLHttpRequest
  • Fetch API
  • Canvas
  • WebSockets

This changed with the introduction of the Typed Array API, whose main use cases are:

Processing binary data: manipulating image data in HTML Canvas elements, parsing binary files, handling binary network protocols, etc.

Interacting with native APIs: Native APIs often receive and return data in a binary format, which you could neither store nor manipulate well in traditional JavaScript. That meant that whenever you were communicating with such an API, data had to be converted from JavaScript to binary and back, for every call. Typed Arrays eliminate this bottleneck. One example of communicating with native APIs is WebGL, for which Typed Arrays were initially created. Section “History of Typed Arrays” of the article “Typed Arrays: Binary Data in the Browser” (by Ilmari Heikkinen for HTML5 Rocks) has more information.

Two kinds of objects work together in the Typed Array API:

  • Buffers: Instances of ArrayBuffer hold the binary data.
  • Views: provide the methods for accessing the binary data. There are two kinds of views:
    1. An instance of a Typed Array constructor (Uint8Array, Float64Array, etc.) works much like a normal Array, but only allows a single type for its elements and doesn’t have holes.
    2. An instance of DataView lets you access data at any byte offset in the buffer, and interprets that data as one of several types (Uint8, Float64, etc.).

This is a diagram of the structure of the Typed Array API (notable: all Typed Arrays have a common superclass):

16. What is promises? explain with example?

Promises, have been around quite a while and are defined by a spec called Promise/A+. ES6 has adopted this spec for its Promise implementation; but there are other Promise libraries out there such as Q, Bluebird, RSVP and others that adhere to this spec and offer other features on top of it.

Promises give us a way to handle asynchronous processing in a more synchronous fashion. They represent a value that we can handle at some point in the future. And, better than callbacks here, Promises give us guarantees about that future value, specifically:

  1. 1. No other registered handlers of that value can change it (the Promise is immutable)
  2. 2. We are guaranteed to receive the value, regardless of when we register a handler for it, even if it's already resolved (in contrast to events, which can incur race conditions).

For example:

// an immediately resolved promise
var p2 = Promise.resolve("foo"); 

// can get it after the fact, unlike events
p2.then((res) => console.log(res)); 

var p = new Promise(function(resolve, reject) {  
   setTimeout(() => resolve(4), 2000);
});

// handler can't change promise, just value
p.then((res) => {  
  res += 2;  
  console.log(res);
});

// still gets 4
p.then((res) => console.log(res));  

No comments:

Post a Comment

Pages