One place for hosting & domains

      Functions

      How To Use the all, any, max, and min Functions in Python


      The author selected the COVID-19 Relief Fund to receive a donation as part of the Write for DOnations program.

      Introduction

      Python includes a number of built-in functions—these are global Python functions that can be called from any Python code without importing additional modules. For example, you can always call the print built-in function to output text.

      Several of the built-in functions (all, any, max, and min among them) take iterables of values as their argument and return a single value. An iterable is a Python object that can be “iterated over”, that is, it will return items in a sequence such that you can use it in a for loop. Built-in functions are useful when, for example, you want to determine if all or any of the elements in a list meet a certain criteria, or find the largest or smallest element in a list.

      In this tutorial, you will use the built-in functions all, any, max, and min.

      Prerequisites

      To get the most out of this tutorial, it is recommended to have:

      Using all

      The built-in function all checks if every element in an iterable is True. For example:

      all([True, True])
      

      If you run the previous code, you will receive this output:

      Output

      True

      In this first example, you call all and give it a list with two elements (two True Boolean values). Since every element in the iterable is True, the output was True.

      all will return False if one or more elements in the given iterable is False:

      all([True, False, True])
      

      If you run the previous code, you’ll receive this output:

      Output

      False

      You call all with a list containing three elements including one False Boolean value. Since one of the elements in the iterable was False, the output of the call to all was False.

      Notably, all stops iterating and immediately returns False as soon as it encounters the first False entry in an iterable. So, all can be useful if you want to check successive conditions that may build on each other, but return immediately as soon as one condition is False.

      A special case to be aware of is when all is given an empty iterable:

      all([])
      

      If you run the previous code, you’ll receive this output:

      Output

      True

      When you give all an empty iterable (for example, an empty list like all([])), its return value is True. So, all returns True if every element in the iterable is True or there are 0 elements.

      all is particularly helpful when combined with generators and custom conditions. Using all is often shorter and more concise than if you were to write a full-fledged for loop. Let’s consider an example to find out whether there are elements in a list that start with "s":

      animals = ["shark", "seal", "sea urchin"]
      all(a.startswith("s") for a in animals)
      

      If you run the previous code, you will receive this output:

      Output

      True

      You call all with a generator as its argument. The generator produces a Boolean for each element in the animals list based on whether or not the animal starts with the letter s. The final return value is True because every element in the animals list starts with s.

      Note: You can often use Generator expressions in place of list comprehensions as a way of saving memory. For example, consider all(i < 8 for i in range(3)) and all([i < 8 for i in range(3)]). Both statements return True because 0, 1, 2 are all less than 8. The second example (which uses a list comprehension), however, has the added overhead of implicitly creating a list three entries long ([True, True, True]) and then passing that list to the all function. The first example (which uses generator expressions), by contrast, passes a generator object to the all function, which the all function iterates over directly without the overhead of an intermediary list.

      Consider that the equivalent code written using a full-fledged for loop would have been significantly more verbose:

      animals = ["shark", "seal", "sea urchin"]
      
      def all_animals_start_with_s(animals):
          for a in animals:
              if not a.startswith("s"):
                  return False
          return True
      
      print(all_animals_start_with_s(animals))
      

      Without all, your code for determining if all the animals start with the letter s requires several more lines to implement.

      Next, you’ll look at the sibling function to all: any.

      Using any

      You can use the built-in function any to check if any element in an iterable is True. For example:

      any([False, True])
      

      If you run the previous code, you’ll receive this output:

      Output

      True

      You call any and give it a list with two elements (a False Boolean value and a True Boolean value). Since one or more element in the iterable was True, the output was also True.

      any will return False if, and only if, 0 of the elements in the given iterable are True:

      all([False, False, False])
      

      If you run the previous code, you’ll receive this output:

      Output

      False

      You call any with a list containing three elements (all False Boolean values). Since 0 of the elements in the iterable is True, the output of the call to any is False.

      Notably, any stops iterating and immediately returns True as soon as it encounters the first True entry in an iterable. So, any can be useful if you want to check successive conditions, but return immediately as soon as one condition is True.

      any—like its sibling method all—is particularly helpful when combined with generators and custom conditions (in place of a full for loop). Let’s consider an example to find out whether there are elements in a list that end with "urchin":

      animals = ["shark", "seal", "sea urchin"]
      any(s.endswith("urchin") for s in animals)
      

      You will receive this output:

      Output

      True

      You call any with a generator as its argument. The generator produces a Boolean for each element in the animals list based on whether or not the animal ends with urchin. The final return value is True because one element in the animals list ends with urchin.

      Note: When any is given an empty iterable (for example, an empty list like any([])), its return value is False. So, any returns False if there are 0 elements in the iterable or all the elements in the iterable are also False.

      Next, you’ll review another built-in function: max.

      Using max

      The built-in function max returns the largest element given in its arguments. For example:

      max([0, 8, 3, 1])
      

      max is given a list with four integers as its argument. The return value of max is the largest element in that list: 8.

      The output will be the following:

      Output

      8

      If given two or more positional arguments (as opposed to a single positional argument with an iterable), max returns the largest of the given arguments:

      max(1, -1, 3)
      

      If you run the previous code, you will receive this output:

      Output

      3

      max is given three individual arguments, the largest of which being 3. So, the return value of the call to max is 3.

      Just like any and all, max is particularly helpful because it requires fewer lines to use than equivalent code written as a full for loop.

      max can also deal with objects more complex than numbers. For example, you can use max with dictionaries or other custom objects in your program. max can accommodate these objects by using its keyword argument named key.

      You can use the key keyword argument to define a custom function that determines the value used in the comparisons to determine the maximum value. For example:

      entries = [{"id": 9}, {"id": 17}, {"id": 4}]
      max(entries, key=lambda x: x["id"])
      

      The output will be the following:

      Output

      {'id': 17}

      You call max with a list of dictionaries as its input. You give an anonymous lambda function as the key keyword argument. max calls the lambda function for every element in the entries list and returns the value of the "id" key of the given element. The final return value is the second element in entries: {"id": 17}. The second element in entries had the largest "id" value, and so was deemed to be the maximum element.

      Note that when max is called with an empty iterable, it refuses to operate and instead raises a ValueError:

      max([])
      

      If you run this code, you will receive the following output:

      Output

      Traceback (most recent call last): File "max.py", line 1, in <module> max([]) ValueError: max() arg is an empty sequence

      You call max with an empty list as its argument. max does not accept this as a valid input, and raises a ValueError Exception instead.

      max has a counterpart called min, which you’ll review next.

      Using min

      The built-in function min returns the smallest element given in its arguments. For example:

      min([8, 0, 3, 1])
      

      You give min a list with four integers as its argument. The return value of min is the smallest element in that list: 0.

      The output will be:

      Output

      0

      If given two or more positional arguments (as opposed to a single positional argument with an iterable), min returns the smallest of the given arguments:

      min(1, -1, 3)
      

      If you run the previous code, you will receive this output:

      Output

      -1

      You give min three individual arguments, the smallest of which being -1. So, the return value of the call to min is -1.

      Like max, min supports the keyword argument named key so that you can pass objects more complex than numbers into it. Using the key argument allows you to use the min function with any custom objects your program might define.

      You can use the key keyword argument to define a custom function that determines the value used in the comparisons to determine the minimum value. For example:

      entries = [{"id": 9}, {"id": 17}, {"id": 4}]
      min(entries, key=lambda x: x["id"])
      

      Output

      {'id': 4}

      You call min with a list of dictionaries as its input. You give an anonymous lambda function as the key keyword argument. min calls the lambda function for every element in the entries list and returns the value of the "id" key of the given element. The final return value is the third element in entries: {"id": 4}. The third element in entries had the smalled "id" value, and so was deemed to be the minimum element.

      Like max, when you call min with an empty iterable, it refuses to operate and instead raises a ValueError:

      min([])
      

      If you run the previous code, you will receive this output:

      Output

      Traceback (most recent call last): File "min.py", line 1, in <module> min([]) ValueError: min() arg is an empty sequence

      You call min with an empty list as its argument. min does not accept this as a valid input, and raises a ValueError Exception instead.

      Conclusion

      In this tutorial, you used the Python built-in functions all, any, max, and min. You can learn more about the functions all, any, max, and min and other Python built-in in the Python docs.

      For more information on other Python built-ins, you can also check out Built-in Python 3 Functions for Working with Numbers, How To Use the Python Map Function, and How To Use the Python Filter Function.



      Source link

      Exploring Async/Await Functions in JavaScript


      Introduction

      Promises give us an easier way to deal with asynchrony in our code in a sequential manner. Considering that our brains are not designed to deal with asynchronicity efficiently, this is a much welcome addition. Async/await functions, a new addition with ES2017 (ES8), help us even more in allowing us to write completely synchronous-looking code while performing asynchronous tasks behind the scenes.

      The functionality achieved using async functions can be recreated by combining promises with generators, but async functions give us what we need without any extra boilerplate code.

      Simple Example

      In the following example, we first declare a function that returns a promise that resolves to a value of 🤡 after 2 seconds. We then declare an async function and await for the promise to resolve before logging the message to the console:

      function scaryClown() {
        return new Promise(resolve => {
          setTimeout(() => {
            resolve('🤡');
          }, 2000);
        });
      }
      
      async function msg() {
        const msg = await scaryClown();
        console.log('Message:', msg);
      }
      
      msg(); // Message: 🤡 <-- after 2 seconds
      

      await is a new operator used to wait for a promise to resolve or reject. It can only be used inside an async function.

      The power of async functions becomes more evident when there are multiple steps involved:

      function who() {
        return new Promise(resolve => {
          setTimeout(() => {
            resolve('🤡');
          }, 200);
        });
      }
      
      function what() {
        return new Promise(resolve => {
          setTimeout(() => {
            resolve('lurks');
          }, 300);
        });
      }
      
      function where() {
        return new Promise(resolve => {
          setTimeout(() => {
            resolve('in the shadows');
          }, 500);
        });
      }
      
      async function msg() {
        const a = await who();
        const b = await what();
        const c = await where();
      
        console.log(`${ a } ${ b } ${ c }`);
      }
      
      msg(); // 🤡 lurks in the shadows <-- after 1 second
      

      A word of caution however, in the above example each step is done sequentially, with each additional step waiting for the step before to resolve or reject before continuing. If you instead want the steps to happen in parallel, you can simply use Promise.all to wait for all the promises to have fulfilled:

      // ...
      
      async function msg() {
        const [a, b, c] = await Promise.all([who(), what(), where()]);
      
        console.log(`${ a } ${ b } ${ c }`);
      }
      
      msg(); // 🤡 lurks in the shadows <-- after 500ms
      

      Promise.all returns an array with the resolved values once all the passed-in promises have resolved.

      In the above we also make use of some nice array destructuring to make our code succinct.

      Promise-Returning

      Async functions always return a promise, so the following may not produce the result you’re after:

      async function hello() {
        return 'Hello Alligator!';
      }
      
      const b = hello();
      
      console.log(b); // [object Promise] { ... }
      

      Since what’s returned is a promise, you could do something like this instead:

      async function hello() {
        return 'Hello Alligator!';
      }
      
      const b = hello();
      
      b.then(x => console.log(x)); // Hello Alligator!
      

      …or just this:

      async function hello() {
        return 'Hello Alligator!';
      }
      
      hello().then(x => console.log(x)); // Hello Alligator!
      

      Different Forms

      So far with our examples we saw the async function as a function declaration, but you we can also define async function expressions and async arrow functions:

      Async Function Expression

      Here’s the async function from our first example, but defined as a function expression:

      const msg = async function() {
        const msg = await scaryClown();
        console.log('Message:', msg);
      }
      

      Async Arrow Function

      Here’s that same example once again, but this time defined as an arrow function:

      const msg = async () => {
        const msg = await scaryClown();
        console.log('Message:', msg);
      }
      

      Error Handling

      Something else that’s very nice about async functions is that error handling is also done completely synchronously, using good old try…catch statements. Let’s demonstrate by using a promise that will reject half the time:

      function yayOrNay() {
        return new Promise((resolve, reject) => {
          const val = Math.round(Math.random() * 1); // 0 or 1, at random
      
          val ? resolve('Lucky!!') : reject('Nope 😠');
        });
      }
      
      async function msg() {
        try {
          const msg = await yayOrNay();
          console.log(msg);
        } catch(err) {
          console.log(err);
        }
      }
      
      msg(); // Lucky!!
      msg(); // Lucky!!
      msg(); // Lucky!!
      msg(); // Nope 😠
      msg(); // Lucky!!
      msg(); // Nope 😠
      msg(); // Nope 😠
      msg(); // Nope 😠
      msg(); // Nope 😠
      msg(); // Lucky!!
      

      Given that async functions always return a promise, you can also deal with unhandled errors as you would normally using a catch statement:

      async function msg() {
        const msg = await yayOrNay();
        console.log(msg);
      }
      
      msg().catch(x => console.log(x));
      

      This synchronous error handling doesn’t just work when a promise is rejected, but also when there’s an actual runtime or syntax error happening. In the following example, the second time with call our msg function we pass in a number value that doesn’t have a toUpperCase method in its prototype chain. Our try…catch block catches that error just as well:

      function caserUpper(val) {
        return new Promise((resolve, reject) => {
          resolve(val.toUpperCase());
        });
      }
      
      async function msg(x) {
        try {
          const msg = await caserUpper(x);
          console.log(msg);
        } catch(err) {
          console.log('Ohh no:', err.message);
        }
      }
      
      msg('Hello'); // HELLO
      msg(34); // Ohh no: val.toUpperCase is not a function
      

      Async Functions With Promise-Based APIS

      As we showed in our primer to the Fetch API, web APIs that are promise-based are a perfect candidate for async functions:

      async function fetchUsers(endpoint) {
        const res = await fetch(endpoint);
        let data = await res.json();
      
        data = data.map(user => user.username);
      
        console.log(data);
      }
      
      fetchUsers('https://jsonplaceholder.typicode.com/users');
      // ["Bret", "Antonette", "Samantha", "Karianne", "Kamren", "Leopoldo_Corkery", "Elwyn.Skiles", "Maxime_Nienow", "Delphine", "Moriah.Stanton"]
      

      <%>[note]
      Browser Support:
      As of 2020, 94% of browsers worldwide can handle async/await in javascript Notable exceptions are IE11 and Opera Mini.

      Conclusion

      Before Async/await functions, JavaScript code that relied on lots of asynchronous events (for example: code that made lots of calls to APIs) would end up in what some called “callback hell” – A chain of functions and callbacks that was very difficult to read and understand.

      Async and await allow us to write asynchronous JavaScript code that reads much more clearly.



      Source link

      Understanding Arrow Functions in JavaScript


      The author selected the COVID-19 Relief Fund to receive a donation as part of the Write for DOnations program.

      Introduction

      The 2015 edition of the ECMAScript specification (ES6) added arrow function expressions to the JavaScript language. Arrow functions are a new way to write anonymous function expressions, and are similar to lambda functions in some other programming languages, such as Python.

      Arrow functions differ from traditional functions in a number of ways, including the way their scope is determined and how their syntax is expressed. Because of this, arrow functions are particularly useful when passing a function as a parameter to a higher-order function, such as when you are looping over an array with built-in iterator methods. Their syntactic abbreviation can also allow you to improve the readability of your code.

      In this article, you will review function declarations and expressions, learn about the differences between traditional function expressions and arrow function expressions, learn about lexical scope as it pertains to arrow functions, and explore some of the syntactic shorthand permitted with arrow functions.

      Defining Functions

      Before delving into the specifics of arrow function expressions, this tutorial will briefly review traditional JavaScript functions in order to better show the unique aspects of arrow functions later on.

      The How To Define Functions in JavaScript tutorial earlier in this series introduced the concept of function declarations and function expressions. A function declaration is a named function written with the function keyword. Function declarations load into the execution context before any code runs. This is known as hoisting, meaning you can use the function before you declare it.

      Here is an example of a sum function that returns the sum of two parameters:

      function sum(a, b) {
        return a + b
      }
      

      You can execute the sum function before declaring the function due to hoisting:

      sum(1, 2)
      
      function sum(a, b) {
        return a + b
      }
      

      Running this code would give the following output:

      Output

      3

      You can find the name of the function by logging the function itself:

      console.log(sum)
      

      This will return the function, along with its name:

      Output

      ƒ sum(a, b) { return a + b }

      A function expression is a function that is not pre-loaded into the execution context, and only runs when the code encounters it. Function expressions are usually assigned to a variable, and can be anonymous, meaning the function has no name.

      In this example, write the same sum function as an anonymous function expression:

      const sum = function (a, b) {
        return a + b
      }
      

      You’ve now assigned the anonymous function to the sum constant. Attempting to execute the function before it is declared will result in an error:

      sum(1, 2)
      
      const sum = function (a, b) {
        return a + b
      }
      

      Running this will give:

      Output

      Uncaught ReferenceError: Cannot access 'sum' before initialization

      Also, note that the function does not have a named identifier. To illustrate this, write the same anonymous function assigned to sum, then log sum to the console:

      const sum = function (a, b) {
        return a + b
      }
      
      console.log(sum)
      

      This will show you the following:

      Output

      ƒ (a, b) { return a + b }

      The value of sum is an anonymous function, not a named function.

      You can name function expressions written with the function keyword, but this is not popular in practice. One reason you might want to name a function expression is to make error stack traces easier to debug.

      Consider the following function, which uses an if statement to throw an error if the function parameters are missing:

      const sum = function namedSumFunction(a, b) {
        if (!a || !b) throw new Error('Parameters are required.')
      
        return a + b
      }
      
      sum();
      

      The highlighted section gives the function a name, and then the function uses the or || operator to throw an error object if either of the parameters is missing.

      Running this code will give you the following:

      Output

      Uncaught Error: Parameters are required. at namedSumFunction (<anonymous>:3:23) at <anonymous>:1:1

      In this case, naming the function gives you a quick idea of where the error is.

      An arrow function expression is an anonymous function expression written with the “fat arrow” syntax (=>).

      Rewrite the sum function with arrow function syntax:

      const sum = (a, b) => {
        return a + b
      }
      

      Like traditional function expressions, arrow functions are not hoisted, and so you cannot call them before you declare them. They are also always anonymous—there is no way to name an arrow function. In the next section, you will explore more of the syntactical and practical differences between arrow functions and traditional functions.

      Arrow Function Behavior and Syntax

      Arrow functions have a few important distinctions in how they work that distinguish them from traditional functions, as well as a few syntactic enhancements. The biggest functional differences are that arrow functions do not have their own this binding or prototype and cannot be used as a constructor. Arrow functions can also be written as a more compact alternative to traditional functions, as they grant the ability to omit parentheses around parameters and add the concept of a concise function body with implicit return.

      In this section, you will go through examples that illustrate each of these cases.

      Lexical this

      The keyword this is often considered a tricky topic in JavaScript. The article Understanding This, Bind, Call, and Apply in JavaScript explains how this works, and how this can be implicitly inferred based on whether the program uses it in the global context, as a method within an object, as a constructor on a function or class, or as a DOM event handler.

      Arrow functions have lexical this, meaning the value of this is determined by the surrounding scope (the lexical environment).

      The next example will demonstrate the difference between how traditional and arrow functions handle this. In the following printNumbers object, there are two properties: phrase and numbers. There is also a method on the object, loop, which should print the phrase string and the current value in numbers:

      const printNumbers = {
        phrase: 'The current value is:',
        numbers: [1, 2, 3, 4],
      
        loop() {
          this.numbers.forEach(function (number) {
            console.log(this.phrase, number)
          })
        },
      }
      

      One might expect the loop function to print the string and current number in the loop on each iteraton. However, in the result of running the function the phrase is actually undefined:

      printNumbers.loop()
      

      This will give the following:

      Output

      undefined 1 undefined 2 undefined 3 undefined 4

      As this shows, this.phrase is undefined, indicating that this within the anonymous function passed into the forEach method does not refer to the printNumbers object. This is because a traditional function will not determine its this value from the scope of the environment, which is the printNumbers object.

      In older versions of JavaScript, you would have had to use the bind method, which explicitly sets this. This pattern can be found often in some earlier versions of frameworks, like React, before the advent of ES6.

      Use bind to fix the function:

      const printNumbers = {
        phrase: 'The current value is:',
        numbers: [1, 2, 3, 4],
      
        loop() {
          // Bind the `this` from printNumbers to the inner forEach function
          this.numbers.forEach(
            function (number) {
              console.log(this.phrase, number)
            }.bind(this),
          )
        },
      }
      
      printNumbers.loop()
      

      This will give the expected result:

      Output

      The current value is: 1 The current value is: 2 The current value is: 3 The current value is: 4

      Arrow functions provide a more direct way of dealing with this. Since their this value is determined based on the lexical scope, the inner function called in forEach can now access the properties of the outer printNumbers object, as demonstrated:

      const printNumbers = {
        phrase: 'The current value is:',
        numbers: [1, 2, 3, 4],
      
        loop() {
          this.numbers.forEach((number) => {
            console.log(this.phrase, number)
          })
        },
      }
      
      printNumbers.loop()
      

      This will give the expected result:

      Output

      The current value is: 1 The current value is: 2 The current value is: 3 The current value is: 4

      These examples establish that using arrow functions in built-in array methods like forEach, map, filter, and reduce can be more intuitive and easier to read, making this strategy more likely to fulfill expectations.

      Arrow Functions as Object Methods

      While arrow functions are excellent as parameter functions passed into array methods, they are not effective as object methods because of the way they use lexical scoping for this. Using the same example as before, take the loop method and turn it into an arrow function to discover how it will execute:

      const printNumbers = {
        phrase: 'The current value is:',
        numbers: [1, 2, 3, 4],
      
        loop: () => {
          this.numbers.forEach((number) => {
            console.log(this.phrase, number)
          })
        },
      }
      

      In this case of an object method, this should refer to properties and methods of the printNumbers object. However, since an object does not create a new lexical scope, an arrow function will look beyond the object for the value of this.

      Call the loop() method:

      printNumbers.loop()
      

      This will give the following:

      Output

      Uncaught TypeError: Cannot read property 'forEach' of undefined

      Since the object does not create a lexical scope, the arrow function method looks for this in the outer scope–Window in this example. Since the numbers property does not exist on the Window object, it throws an error. As a general rule, it is safer to use traditional functions as object methods by default.

      Arrow Functions Have No constructor or prototype

      The Understanding Prototypes and Inheritance in JavaScript tutorial earlier in this series explained that functions and classes have a prototype property, which is what JavaScript uses as a blueprint for cloning and inheritance.

      To illustrate this, create a function and log the the automatically assigned prototype property:

      function myFunction() {
        this.value = 5
      }
      
      // Log the prototype property of myFunction
      console.log(myFunction.prototype)
      

      This will print the following to the console:

      Output

      {constructor: ƒ}

      This shows that in the prototype property there is an object with a constructor. This allows you to use the new keyword to create an instance of the function:

      const instance = new myFunction()
      
      console.log(instance.value)
      

      This will yield the value of the value property that you defined when you first declared the function:

      Output

      5

      In contrast, arrow functions do not have a prototype property. Create a new arrow function and try to log its prototype:

      const myArrowFunction = () => {}
      
      // Attempt to log the prototype property of myArrowFunction
      console.log(myArrowFunction.prototype)
      

      This will give the following:

      Output

      undefined

      As a result of the missing prototype property, the new keyword is not available and you cannot construct an instance from the arrow function:

      const arrowInstance = new myArrowFunction()
      
      console.log(arrowInstance)
      

      This will give the following error:

      Output

      Uncaught TypeError: myArrowFunction is not a constructor

      This is consistent with our earlier example: Since arrow functions do not have their own this value, it follows that you would be unable to use an arrow function as a constructor.

      As shown here, arrow functions have a lot of subtle changes that make them operate differently from traditional functions in ES5 and earlier. There have also been a few optional syntactical changes that make writing arrow functions quicker and less verbose. The next section will show examples of these syntax changes.

      Implicit Return

      The body of a traditional function is contained within a block using curly brackets {} and ends when the code encounters a return keyword. The following is what this implementation looks like as an arrow function:

      const sum = (a, b) => {
        return a + b
      }
      

      Arrow functions introduce concise body syntax, or implicit return. This allows the omission of the curly brackets and the return keyword.

      const sum = (a, b) => a + b
      

      Implicit return is useful for creating succinct one-line operations in map, filter, and other common array methods. Note that both the brackets and the return keyword must be omitted. If you cannot write the body as a one-line return statement, then you will have to use the normal block body syntax.

      In the case of returning an object, syntax requires that you wrap the object literal in parentheses. Otherwise, the brackets will be treated as a function body and will not compute a return value.

      To illustrate this, find the following example:

      const sum = (a, b) => ({result: a + b})
      
      sum(1, 2)
      

      This will give the following output:

      Output

      {result: 3}

      Omitting Parentheses Around a Single Parameter

      Another useful syntactic enhancement is the ability to remove parentheses from around a single parameter in a function. In the following example, the square function only operates on one parameter, x:

      const square = (x) => x * x
      

      As a result, you can omit the parentheses around the parameter, and it will work just the same:

      const square = x => x * x
      
      square(10)
      

      This will give the following:

      Output

      100

      Note that if a function takes no parameters, parentheses will be required:

      const greet = () => 'Hello!'
      
      greet()
      

      Calling greet() will work as follows:

      Output

      'Hello!'

      Some codebases choose to omit parentheses wherever possible, and others choose to always keep parentheses around parameters no matter what, particularly in codebases that use TypeScript and require more information about each variable and parameter. When deciding how to write your arrow functions, check the style guide of the project to which you are contributing.

      Conclusion

      In this article, you reviewed traditional functions and the difference between function declarations and function expressions. You learned that arrow functions are always anonymous, do not have a prototype or constructor, cannot be used with the new keyword, and determine the value of this through lexical scope. Finally, you explored the new syntactic enhancements available to arrow functions, such as implicit return and parentheses omission for single parameter functions.

      For a review of basic functions, read How To Define Functions in JavaScript. To read more about the concept of scope and hoisting in JavaScript, read Understanding Variables, Scope, and Hoisting in JavaScript.



      Source link