JavaScriptmas 2020

Test your expertise!

And take your prize!

ES2019+

Question 1

(null || 0) ?? "foo"; 
// what is the result

Question 2

const a = { duration: 50 };

a.duration ??= 10;
console.log(a.duration);

Question 3

let x = 1 && 2 ?? 3; 

Nullish coalescing operator '??'

Short way to choose the first “defined” value from a list.

const happiness = null;
const howAreYou = happines ?? 'OK'
 // mood is OK

Have you ever used || to set a default value if a variable was null or undefined?

Differences with || operator

const cokies = 0;
const howAreYou = cokies ?? 'Not clear' // 0
const anyCookies = cokies || 'Not clear' // Not clear

It’s forbidden to use it with || or && without explicit parentheses.

let x = 1 && 2 ?? 3; // Error

let y = (1 && 2) ?? 3; // OK

Logical nullish assignment (??=)

const book = { title: 'Dogs' };
​
// book.title is NOT nullish
book.title ??= 'Cats';
console.log(book.title);
// expected output: 'Dogs'
​
// book.author is nullish
book.author ??= 'Cameron Manavian';
console.log(book.author);
// expected output: 'Cameron Manavian'

The logical nullish assignment only assigns if the left-hand variable is nullish, which in JavaScript means it is either null or undefined

 nullish assignment

Question 4

const vacations = { trip: {} }
let duration = vacations.trip?.getTime?.();

The optional chaining ?. is not an operator, but a special syntax construct, that also works with functions and square brackets.

let userAdmin = {
  admin() {
    alert("I am admin");
  }
};

let userGuest = {};

userAdmin.admin?.(); // I am admin
userGuest.admin?.(); // nothing (no such method)

Optional Chaining

Question 5

Promise.allSettled([
  
  Promise.resolve(1),
  fetch('/not_existing_url')
  
]).then(() => console.log('Then'))
  .catch(() => console.log('Error'))
  .finally(() => console.log('Finnaly'));
// Success or fail - doesn't metter!
Promise.allSettled([Promise.resolve(1), 
 fetch('/not_existing_url')])
  .then(() => console.log('Then'))
  .catch(() => console.log('Error'))
  .finally(() => console.log('Finnaly'));

// Then Finally

All Settled

Since ES2020 you can use Promise.allSettled. It returns a promise that always resolves after all of the given promises have either fulfilled or rejected, with an array of objects that each describes the outcome of each promise.

ES6+

Question 6

let obj = {cookies: 10 }

// your code

obj.cookies--;

// console error
// "Don't touch my cookies!" appeared

let obj = { cookies: 10 }

obj = new Proxy(obj, {
  set: function(item, property, value){
    if (property === 'cookies') {
		throw new Error(`Don't touch my cookies`)
	} else {
      item[property] = value
    }
  }
})

obj.cookies--

Proxies

There is no other way, for now, to trigger code when a property is added to an object than Proxy.

Question 7

function* gen() { 
  yield 1;
  yield 2;
  yield 3;
  return 4;
}

console.log([...gen()]);

What is "Spread Operator" exactly does ?

The spread operator is used to expand elements of an iterable (like an array) into places where multiple elements can fit.

What is an iterator ?

Object that knows how to access items from a collection one at a time, while keeping track of its current position within that sequence.

The iterator object has a next() method that returns the next item in the sequence.

This method returns an object with two properties: done and value

const genInstance = gen();

genInstance.next();
//{value: 1, done: false}

genInstance.next();
//{value: 2, done: false}

genInstance.next();
//{value: 3, done: false}

genInstance.next();
//{value: 4, done: true}

Spread operator doesn't count objects with "done: true"

function* gen() { 
  yield 1;
  yield 2;
  yield 3;
  return 4;
}

console.log([...gen()]);

// [1, 2, 3]

Question 8

Valid way of canceling fetch request

const promise = fetch(url) 
  .then((response) => {
    return response;
  })
  .catch((err) => {
    console.log(err);
  });

// wait i need to cancel it!

Fetching some data...

And response doesn't come for a while...

Abort a fetch ?

AbortController !

Represents a controller object that allows you to abort one or more Web requests as and when desired

const url = "https://api.github.com/users";

const controller = new AbortController();
const signal = controller.signal;

const promise = fetch(url, {signal}) 
// you can see we pass signal to fetch params
  .then((response) => {
    return response;
  })
  .catch((err) => {
    console.log(err);
  });

controller.abort();

Example

Question 9

function smilify(strings, ...values) {
  return strings.reduce(
    (res, str, idx) => 
        res + str + (values[idx]?.toUpperCase() ?? '❤️'),
    '',
  );
}

smilify`I love ${'js community'}` // <-- result ?

Tagged template strings

const Button = styled.a`
  /* This renders the buttons above... Edit me! */
  display: inline-block;
  border-radius: 3px;
  padding: 0.5rem 0;
  margin: 0.5rem 1rem;
  width: 11rem;
  background: transparent;
  color: white;
  border: 2px solid white;

  ${props => props.primary && css`
    background: white;
    color: black;
  `}
`

Styled components

Works over tagged template strings!

tagged`hello ${'js community'}, this is ${'quiz'}`

strings: ['hello ', ', this is', '']

values: ['js community', 'quiz']

ES5-

Question 10

void function iife() {
 return 1
}();

Void operator

void 0; //returns undefined
void(1); //returns undefined

void 'hello'; //undefined
void {}; //undefined
void []; //undefined

void myFunction(); 
void(myFunction());

The JavaScript, the void operator is used to explicitly return undefined. Its a unary operator, meaning only one operand can be used with it. You can use it like shown below — standalone or with a parenthesis.

But why?

Well, the reason is before ES5 you could actually assign a new value to the original undefined like so undefined = “js snippet”, and most browsers would support it. So as to return the original undefined and just to be double sure the void operator was used.

undefined = true

Thank You!

JavaScriptmas 2020

By Vladimir Vyshko

JavaScriptmas 2020

JavaScriptmas 2020

  • 416