Bo dinglesTM - -   Bright Lightbulb Graphic Ideas   - -

The Web Developer Bootcamp 2024

Colt Steele

Back to JavaScript Index Page


Newer JavaScript Features
Newer JavaScript Features References

Modern JavaScript Features PDF

Here are some Newer JavaScript Features to be aware of:




Default Parameters

In JavaScript you can specify Default Parameters. This is used in instances where a needed parameter is not passed in to a function. Example:

If we take our random number generator,

  • function getRandomNum() {
    • return Math.floor(Math.random() * 6) + 1;
  • }
this will return a random number between 1 and 6, because 6 is specified in the function. What if we wanted a random number between 1 and 10, or 1 and 20, or 1 and any number we may want to specify? We know we can specify any number if we add an argument to pass in to the function like so:
  • function getRandomNum(num) {
    • return Math.floor(Math.random() * num>) + 1;
  • }
we could then feed the random number generator with any number we want by passing in an argument when we call the function:
  • console.log(getRandomNum(10));
This would generate a number between 1 and 10. But what if we do not include the argument when we call the function:
  • console.log(getRandomNum());
This would return NaN because we are trying to find a random number between 1 and NaN. We can avoid this by simply adding a default parameter into the function argument like so:
  • function getRandomNum(num = 6) {

You could still insert any number you wish to feed the random number generator, but if you do not include the argument when you call the function, it would default to 6 and produce a random number between 1 and 6.

Important: the order in which you place the default parameters matters. They are processed in the order the code encounters them, left to right. Lets explain with the following function:

  • function greet(msg, name) {
    • console.log(`${msg}, ${name} !!`)
  • }
if we call this function, greet('Hello', 'Bob'); we would get Hello, Bob !!

Everything is good so far, but what if we give the message parameter a "default", like so:

  • function greet(msg = 'Hey There', name) {
if we call this function with the same parameters, greet('Hello', 'Bob'); we would get the same result: Hello, Bob !!.

But what if we call the function using,

  • greet('Bob');
we would get Bob, undefined !!, because Bob is passed in as the first parameter {msg}, and the second parameter, {name} is undefined. This is because the order of the default parameters matters. Always put the default parameters after any non-default parameters.

So if we change our function so that the default parameter is last like so:

  • function greet(name, msg = 'Hey There') {
and we call the function in the same way:
  • greet('Bob');
we would now get Hey There, Bob !!. remember, the function output was console.log(`${msg}, ${name} !!`);

So, always remember that the order in which you place the default parameters, matters.




Spread (...)

The spread (...) syntax allows an iterable, such as an array or string, to be expanded in places where zero or more arguments (for function calls) or elements (for array literals) are expected. In an object literal, the spread syntax enumerates the properties of an object and adds the key-value pairs to the object being created.

Essentially,

spread (...) allows you to expand iterable objects such as arrays and strings to use the individual elements when a method is looking for seperate arguments. A good example of the is Math.max() which expects seperate arguments.

If we call Math.max(4, 7, 2, 9, 5, 1, 8); this will return the largest number 9 because this is a list of individual numbers (seperate arguments).


But what if we call Math.max() with an array of numbers:

  • let nums = [4, 7, 2, 9, 5, 1, 8];
  • Math.max(nums);
If we try, we get NaN because Math.max() will see the entire array as one single argument. It will not know how to process the individual numbers. This is where spread comes in. It will expand the array into individual arguments so that Math.max() can process it. So if you run:
  • Math.max(...nums);
it returns 9.

This also works with strings. if we console.log('Hello'); we get: Hello. But if we console.log(...'Hello'); we get: H   e   l   l   o. Each letter in the string becomes a (seperate argument)




Rest (...)

While rest use the 3-dot notation (...) like spread, it essentially has the opposite functionality. Spread allows you to expand an array into individual elements for processing, where rest will group items for processing.

For example, if we have the following function:

  • function sum() {
    • return sum.reduce((total, number) => total + number);
  • }
we would want this to return the total of a list of numbers.

but if we called the function sum(3), this would return a TypeError because sum is not a valid function (reduce is looking fo an array of numbers). We would also get the same error if we tried to call the function with multiple numbers, sum(3, 6, 2). Same problem, reduce is looking for an array of numbers.

We can resolve this by using rest. So if we define the same function using rest like so:

  • function sum(...nums) {
    • return nums.reduce((total, number) => total + number);
  • }
and now we can call the function sum() using as many numbers as we like, the rest (...) method will convert the numbers into an array and now reduce() can process the array and return a total.
  • sum(3); // returns 3
  • sum(3, 6, 2); // returns 11

Now this can be used with multiple function elements like so:

  • function raceResults(gold, silver, ...everyoneElse) {
    • console.log(`The Gold Medal goes to : ${gold}`);
    • console.log(`The Silver Medal goes to : ${silver}`);
    • console.log(`and thanks to everyone else : ${everyoneElse}`);
  • }
now lets call this function:
  • raceResults('Sandy', 'Jasper', 'Chico', 'Addie', 'Sadie');

and for the output we get:

  • The Gold Medal goes to : Sandy
  • The Silver Medal goes to : Jasper
  • and thanks to everyone else : Chico, Addie, Sadie
We can see that Sandy was processed first because she was called first. Like wise Jasper was processed second, and everyone else was processed third.




Destructing

Destructing Arrays is a simplified way of pulling out individual elements of an array.

For example, if we have an array

  • const scores = [96840, 65465, 51496, 64824, 16982];
and we wanted to pull out individual elements we could do this like so:
  • const high = scores[0];
  • const second = scores[1];
We can destruct this array and specify it in one line like so:
  • const [high, second] = scores;
*note that this is position based. the first element called will return the first element of the array, the second will return the second, and so on. Also, you could use this with the rest (..) method like so:
  • const [high, second, ...others] = scores;
  • would return 96840, 65465, and [ 51496, 64824, 16982 ] as an array


Destructing Objects works like Destructing Arrays but is used much more commonly. To show this, lets build an object to store user information.

  • const user = {
    • firstName: 'Harvey',
    • lastName: 'Wallbanger',
    • password: '47F78djxdh$x',
    • email: 'harvy@email.com',
    • born: '2000',
    • died: '2020',
    • city: 'Somewhere',
    • state: 'Texas'
  • }

And if we wanted to pull out individual pieces of information we could use: const fname = user.firstname;


But what if we wanted to pullout several pieces of data and assign them to variables, in one call? We could use multiple lines assigning variable = user.data, or we could simplify the process by deconstructing the object, like so:

  • const {firstName, lastName, email} = user;
This will deconstruct the object user, pull out the individual pieces of data (Harvey, Wallbanger, and harvy@email.com), and assign them to the variables (firstName, lastName & email).

Also, you can rename the variable to anything you want. Lets pull out the born but assign it to a variable called yearBorn. We would use

  • const {born: yearBorn} = user;
This will pull the data from user.born and assign it to the variable yearBorn which would output 2000.


But what if we had a second user who did not fill out ALL of the information? Say user2 is still alive so they left the died field blank. If you try to assign that to a viriable, you will get undefined because user2.died would equal nothing (undefined). We can resolve this by assigning a defaul value. Instead of this:

  • const {died: yearDied} = user2; // would return UNDEFINED
we could use:
  • const {died: yearDied = 'N/A'} = user2; // would return N/A instead of UNDEFINED

Back to Top