One place for hosting & domains

      Default

      HAproxy SSL/TLS Warning: Setting tune.ssl.default-dh-param to 1024 by default



      Part of the Series:
      Common HAProxy Errors

      This tutorial series explains how to troubleshoot and fix some of the most common errors that you may encounter when using the HAProxy TCP and HTTP proxy server.

      Each tutorial in this series includes descriptions of common HAProxy configuration, network, filesystem, or permission errors. The series begins with an overview of the commands and log files that you can use to troubleshoot HAProxy. Subsequent tutorials examine specific errors in detail.

      Introduction

      In this tutorial you will learn how to troubleshoot and fix an HAProxy Setting tune.ssl.default-dh-param to 1024 by default warning message using the methods described in the How to Troubleshoot Common HAProxy Errors tutorial at the beginning of this series. One you confirm that your server is generating the warning message, you will learn how to fix it by setting HAProxy’s ssl-dh-param-file configuration option to use a custom dhparams.pem file.

      You may encounter an HAProxy Setting tune.ssl.default-dh-param to 1024 by default warning message when your HAProxy server is configured with an SSL/TLS certificate and the tune.ssl.default-dh-param parameter is not set in HAProxy’s haproxy.cfg configuration file. When the parameter is not set, HAProxy will default to a value of 1024 bits for the Diffie-Hellman key agreement portion of the TLS handshake, which is considered insecure.

      Your HAProxy server may trigger this warning without you knowing about it. You can configure an SSL/TLS certificate and HAProxy will run, but the server may be warning you about the issue in the background. If you aren’t sure whether your HAProxy server is defaulting to a 1024 bit Diffie-Hellman parameter, you can use a tool like the SSL Labs Server Test to check for you. If you receive a report that has a line This server supports weak Diffie-Hellman (DH) key exchange parameters, then your HAProxy server is affected.

      If you have already determined that your HAProxy server is generating a warning about the tune.ssl.default-dh-param setting and you would like to skip troubleshooting, the Resolving a Secure tune.ssl.default-dh-param Warning section at the end of this tutorial explains how to fix the issue.

      Checking for a tune.ssl.default-dh-param Warning Using systemctl

      Following the troubleshooting steps from the How to Troubleshoot Common HAProxy Errors tutorial at the beginning of this series, the first step when you are troubleshooting a Setting tune.ssl.default-dh-param to 1024 by default warning message is to check HAProxy’s status with systemctl.

      The output from systemctl status may contain all the diagnostic information that you need to resolve the error. However, it is important to examine the current status of the haproxy service to ensure that it is running and that any services that rely on it are still able to function while you resolve the warning.

      Use this systemctl command to examine HAProxy’s status on any Linux distribution:

      • sudo systemctl status haproxy.service -l --no-pager

      The -l flag will ensure that systemctl outputs the entire contents of a line, instead of substituting in ellipses () for long lines. The --no-pager flag will output the entire log to your screen without invoking a tool like less that only shows a screen of content at a time.

      Since you are troubleshooting a Setting tune.ssl.default-dh-param to 1024 by default warning message, you should receive output that is similar to the following:

      Output

      ● haproxy.service - HAProxy Load Balancer Loaded: loaded (/usr/lib/systemd/system/haproxy.service; disabled; vendor preset: disabled) Active: active (running) since Tue 2020-10-06 14:31:39 UTC; 2min 31s ago Process: 71406 ExecStartPre=/usr/sbin/haproxy -f $CONFIG -c -q (code=exited, status=0/SUCCESS) Main PID: 71407 (haproxy) . . . Oct 06 14:31:39 bb9fb4c53743 systemd[1]: Starting HAProxy Load Balancer... Oct 06 14:31:39 bb9fb4c53743 haproxy[71407]: [WARNING] 279/143139 (71407) : parsing [/etc/haproxy/haproxy.cfg:69] : 'bind *:5000' : Oct 06 14:31:39 bb9fb4c53743 haproxy[71407]: unable to load default 1024 bits DH parameter for certificate '/etc/haproxy/fullchain.pem'. Oct 06 14:31:39 bb9fb4c53743 haproxy[71407]: , SSL library will use an automatically generated DH parameter. Oct 06 14:31:39 bb9fb4c53743 haproxy[71407]: [WARNING] 279/143139 (71407) : Setting tune.ssl.default-dh-param to 1024 by default, if your workload permits it you should set it to at least 2048. Please set a value >= 1024 to make this warning disappear. Oct 06 14:31:39 bb9fb4c53743 haproxy[71407]: Proxy main started. Oct 06 14:31:39 bb9fb4c53743 haproxy[71407]: Proxy static started. Oct 06 14:31:39 bb9fb4c53743 haproxy[71407]: Proxy app started. Oct 06 14:31:39 bb9fb4c53743 systemd[1]: Started HAProxy Load Balancer.

      There are two important highlighted sections to note in this output. The first is the active (running) line, which indicates that HAProxy is available and running. If your server shows a line like Active: failed, then you will need to troubleshoot HAProxy using the methods described in the How to Troubleshoot Common HAProxy Errors tutorial at the beginning of this series.

      The second set of highlighted lines are from the systemd journal and contain the tune.ssl.default-dh-param warning. These lines give you all the information about the warning, how it is triggered, the steps taken by HAProxy, and how to resolve it.

      If your systemctl output includes lines with the tune.ssl.default-dh-param warning, then skip to the [Resolving a tune.ssl.default-dh-param Warning](resolving-a-tunessldefault-dh-param-warning) section at the end of this tutorial to learn how to configure HAProxy with a more secure value.

      Otherwise if your systemctl output does not give specific information about the warning, but you know that your server is using weak Diffie-Hellman parameters, the next section of this tutorial will guide you through using journalctl logs to locate the warning message.

      Checking for a tune.ssl.default-dh-param Warning Using journalctl

      If your systemctl output does not include a tune.ssl.default-dh-param warning but you know that your server is affected, you should proceed with using the journalctl command to examine systemd logs for HAProxy.

      Run the following command on any Linux distribution to inspect the systemd journal’s logs for the haproxy service:

      • sudo journalctl -u haproxy.service -l --no-pager | grep tune.ssl.default-dh-param

      The | grep tune.ssl.default-dh-param portion of the command uses a pipe (|) to send the output from journalctl to the grep command as input. Using the pipe means that only matching lines from the journal will be shown on your screen.

      If the journal includes a tune.ssl.default-dh-param warning, then you will receive output like the following:

      Output

      Oct 06 14:31:39 bb9fb4c53743 haproxy[71407]: [WARNING] 279/143139 (71407) : Setting tune.ssl.default-dh-param to 1024 by default, if your workload permits it you should set it to at least 2048. Please set a value >= 1024 to make this warning disappear.

      Since this output includes the warning you can skip to the Setting a Secure tune.ssl.default-dh-param Value section at the end of this tutorial to learn how to configure HAProxy with a more secure value.

      If you do not receive any output after running the journaltcl command, the next section will demonstrate how you can check for a tune.ssl.default-dh-param warning using HAProxy’s built-in configuration checking tool.

      Checking for a tune.ssl.default-dh-param Warning Using haproxy -c or Log Files

      HAProxy includes a command that can examine and validate its configuration files. You can use the command to check for syntax errors or invalid settings without restarting HAProxy and risking downtime for your services. Additionally, if your HAProxy server is configured to log output to a file or the system logs, you can examine the log files to check for a tune.ssl.default-dh-param warning.

      To check for a tune.ssl.default-dh-param warning using HAProxy itself, run the following command on any Linux distribution. If your HAProxy configuration file is in a different location than the highlighted /etc/haproxy/haproxy.cfg path, be sure to substitute in the correct path to your file:

      • sudo haproxy -c -f /etc/haproxy/haproxy.cfg

      If your server is configured with SSL/TLS and does not have a tune.ssl.default-dh-param set, then you will receive warning output similar to the following:

      Output

      [WARNING] 279/150829 (71512) : parsing [/etc/haproxy/haproxy.cfg:69] : 'bind *:5000' : unable to load default 1024 bits DH parameter for certificate '/etc/haproxy/fullchain.pem'. , SSL library will use an automatically generated DH parameter. [WARNING] 279/150829 (71512) : Setting tune.ssl.default-dh-param to 1024 by default, if your workload permits it you should set it to at least 2048. Please set a value >= 1024 to make this warning disappear. Configuration file is valid

      The highlighted line contains the tune.ssl.default-dh-param warning.

      To check for the warning message using HAProxy’s logs, you can search for lines that match the tune.ssl.default-dh-param string using the grep command. Run the following command to check for warnings:

      • sudo grep tune.ssl.default-dh-param /var/log/haproxy.log

      Note that if you have configured HAproxy with a different log location, be sure to substitute in your path in place of the highlighted /var/log/haproxy.log file.

      If your server is generating the warning, then you will receive output like the following:

      Output

      Oct 6 14:31:39 bb9fb4c53743 haproxy[71407]: [WARNING] 279/143139 (71407) : Setting tune.ssl.default-dh-param to 1024 by default, if your workload permits it you should set it to at least 2048. Please set a value >= 1024 to make this warning disappear.

      Note: Your log files may not include the warning message, but the haproxy -c command will still generate the warning. If this is the case, then it is likely that your HAproxy service has been running for long enough that the log file was rotated, so it does not include the warning.

      Checking for the message using the haproxy -c method is the most reliable way to determine if your server is affected, so you can safely disregard missing log file entries.

      Now that you have determined whether your server is generating a tune.ssl.default-dh-param warning, you can proceed to the next step in this tutorial, which explains two methods that you can use to resolve the issue.

      Resolving a tune.ssl.default-dh-param Warning

      You can resolve a tune.ssl.default-dh-param warning in HAProxy with a few different settings. One option is to set the tune.ssl.default-dh-param value to something larger than 1024 explicitly in /etc/haproxy/haproxy.cfg per the warning message. However, the HAProxy documentation recommends specifying custom Diffie-Hellman parameters since that approach is more secure, so we’ll use that method instead.

      First you’ll generate a dhparams.pem file using the openssl utility. Once the file is created, you’ll add it to your global HAProxy configuration section so that any frontend blocks will inherit the setting.

      To generate the custom DH parameters, run the following:

      • sudo openssl dhparam -out /etc/haproxy/dhparams.pem 2048

      You will receive output like the following:

      Output

      Generating DH parameters, 2048 bit long safe prime, generator 2 This is going to take a long time ..............

      Once the command completes, configure HAProxy to use the custom DH parameters file. Open /etc/haproxy/haproxy.cfg in vi or your preferred editor.

      sudo vi /etc/haproxy/haproxy.cfg
      

      Find the section in the file like the following:

      Output

      . . . # turn on stats unix socket stats socket /var/lib/haproxy/stats # utilize system-wide crypto-policies #ssl-default-bind-ciphers PROFILE=SYSTEM ssl-default-server-ciphers PROFILE=SYSTEM

      Now add a line after the ssl-default-server-ciphers PROFILE=SYSTEM line like this:

      ssl-dh-param-file /etc/haproxy/dhparams.pem
      

      The entire section should resemble the following, including the new highlighted ssl-dh-param-file line that you added:

      /etc/haproxy/haproxy.cfg

      . . . # turn on stats unix socket stats socket /var/lib/haproxy/stats # utilize system-wide crypto-policies #ssl-default-bind-ciphers PROFILE=SYSTEM ssl-default-server-ciphers PROFILE=SYSTEM ssl-dh-param-file /etc/haproxy/dhparams.pem

      When you are done editing the file, save and close it by pressing ESC, typing :wq, and pressing ENTER.

      Test the configuration using the haproxy -c command to ensure that you have added the correct setting and that HAProxy can access the custom dhparams.pem file:

      • sudo haproxy -c -f /etc/haproxy/haproxy.cfg

      You should receive output stating that the configuration is valid like the following:

      Output

      Configuration file is valid

      If your configuration is valid, restart HAProxy so that it uses the new Diffie-Hellman parameters file:

      • sudo systemctl restart haproxy.service

      You have now configured HAProxy with a 2048 bit set of custom Diffie-Hellman parameters that all frontends will be able to use. You have also suppressed the tune.ssl.default-dh-param warnings.

      Conclusion

      In this tutorial, you learned how to troubleshoot an HAProxy Setting tune.ssl.default-dh-param to 1024 by default warning message. You explored four different methods to examine HAProxy’s configuration to find the message. First you used systemctl and journalctl to examine the status of the HAProxy server and try to find the message in the systemd logs. Then you examined the HAProxy configuration file using the built in haproxy -c configuration check. Finally you checked for log entries using the grep command on HAProxy’s log file.

      After you confirmed that your server was generating a Setting tune.ssl.default-dh-param to 1024 by default warning message, you generated a custom Diffie-Hellman parameters file and configured HAProxy to use it by setting the ssl-dh-param-file configuration directive.

      Now that you have that configuration in place, your HAProxy server will default to using the more secure Diffie-Hellman parameters, and the tune.ssl.default-dh-param warning message will no longer be in your logs.



      Source link

      How To Install MongoDB from the Default APT Repositories on Ubuntu 20.04


      Introduction

      MongoDB is a free and open-source NoSQL document database used commonly in modern web applications.

      In this tutorial you’ll install MongoDB, manage its service, and optionally enable remote access.

      Note: As of this writing, this tutorial installs version 3.6 of MongoDB, which is the version available from the default Ubuntu repositories. However, we generally recommend installing the latest version of MongoDB — version 4.4 as of this writing — instead. If you’d like to install the latest version of MongoDB, we encourage you to follow this guide on How To Install MongoDB on Ubuntu 20.04 from source.

      Prerequisites

      To follow this tutorial, you will need:

      • One Ubuntu 20.04 server set up by following this initial server setup tutorial, including a non-root user with administrative privileges and a firewall configured with UFW.

      Step 1 — Installing MongoDB

      Ubuntu’s official package repositories include MongoDB, which means we can install the necessary packages using apt. As mentioned in the introduction, the version available from the default repositories is not the latest one. To install the latest version of Mongo, please follow this tutorial instead.

      First, update the packages list to have the most recent version of the repository listings:

      Now install the MongoDB package itself:

      This command will prompt you to confirm that you want to install the mongodb package and its dependencies. To do so, press Y and then ENTER.

      This command installs several packages containing a stable version of MongoDB, along with helpful management tools for the MongoDB server. The database server is automatically started after installation.

      Next, let’s verify that the server is running and works correctly.

      Step 2 — Checking the Service and Database

      The installation process started MongoDB automatically, but let’s verify that the service is started and that the database is working.

      First, check the service’s status:

      • sudo systemctl status mongodb

      You’ll see this output:

      Output

      ● mongodb.service - An object/document-oriented database Loaded: loaded (/lib/systemd/system/mongodb.service; enabled; vendor preset: enabled) Active: active (running) since Thu 2020-10-08 14:23:22 UTC; 49s ago Docs: man:mongod(1) Main PID: 2790 (mongod) Tasks: 23 (limit: 2344) Memory: 42.2M CGroup: /system.slice/mongodb.service └─2790 /usr/bin/mongod --unixSocketPrefix=/run/mongodb --config /etc/mongodb.conf

      According to this output, the MongoDB server is up and running.

      We can verify this further by actually connecting to the database server and executing the following diagnostic command. This will output the current database version, the server address and port, and the output of the status command:

      • mongo --eval 'db.runCommand({ connectionStatus: 1 })'

      Output

      MongoDB shell version v3.6.8 connecting to: mongodb://127.0.0.1:27017 Implicit session: session { "id" : UUID("e3c1f2a1-a426-4366-b5f8-c8b8e7813135") } MongoDB server version: 3.6.8 { "authInfo" : { "authenticatedUsers" : [ ], "authenticatedUserRoles" : [ ] }, "ok" : 1 }

      A value of 1 for the ok field in the response indicates that the server is working properly.

      Next, we’ll look at how to manage the server instance.

      Step 3 — Managing the MongoDB Service

      The installation process outlined in Step 1 configures MongoDB as a systemd service, which means that you can manage it using standard systemctl commands alongside all other system services in Ubuntu.

      To verify the status of the service, type:

      • sudo systemctl status mongodb

      You can stop the server at any time by typing:

      • sudo systemctl stop mongodb

      To start the server when it is stopped, type:

      • sudo systemctl start mongodb

      You can also restart the server with the following command:

      • sudo systemctl restart mongodb

      By default, MongoDB is configured to start automatically with the server. If you wish to disable the automatic startup, type:

      • sudo systemctl disable mongodb

      You can re-enable automatic startup any time with the following command:

      • sudo systemctl enable mongodb

      Next, let’s adjust the firewall settings for our MongoDB installation.

      Step 4 — Adjusting the Firewall (Optional)

      Assuming you have followed the initial server setup tutorial instructions to enable the firewall on your server, the MongoDB server will be inaccessible from the internet.

      If you intend to use the MongoDB server only locally with applications running on the same server, this is the recommended and secure setting. However, if you would like to be able to connect to your MongoDB server from the internet, you have to allow the incoming connections by adding a UFW rule.

      To allow access to MongoDB on its default port 27017 from everywhere, you could run sudo ufw allow 27017. However, enabling internet access to MongoDB server on a default installation gives anyone unrestricted access to the database server and its data.

      In most cases, MongoDB should be accessed only from certain trusted locations, such as another server hosting an application. To only allow access to MongoDB’s default port by another trusted server, you can specify the remote server’s IP address in the ufw command. This way, only that machine will be explicitly allowed to connect:

      • sudo ufw allow from trusted_server_ip/32 to any port 27017

      You can verify the change in firewall settings with ufw:

      You should see traffic to port 27017 allowed in the output. Note that if you have decided to allow only a certain IP address to connect to MongoDB server, the IP address of the allowed location will be listed instead of Anywhere in this command’s output:

      Output

      Status: active To Action From -- ------ ---- OpenSSH ALLOW Anywhere 27017 ALLOW Anywhere OpenSSH (v6) ALLOW Anywhere (v6) 27017 (v6) ALLOW Anywhere (v6)

      You can find more advanced firewall settings for restricting access to services in UFW Essentials: Common Firewall Rules and Commands.

      Even though the port is open, MongoDB will still only be listening on the local address 127.0.0.1. To allow remote connections, add your server’s publicly-routable IP address to the mongodb.conf file.

      Open the MongoDB configuration file in your preferred text editor. This example command uses nano:

      • sudo nano /etc/mongodb.conf

      Add your MongoDB server’s IP address to the bindIP value. Be sure to place a comma between the existing IP address and the one you added:

      /etc/mongodb.conf

      ...
      logappend=true
      
      bind_ip = 127.0.0.1,your_server_ip
      #port = 27017
      
      ...
      

      Save the file and exit the editor. If you used nano to edit the file, do so by pressing CTRL + X, Y, then ENTER.

      Then, restart the MongoDB service:

      • sudo systemctl restart mongodb

      MongoDB is now listening for remote connections, but anyone can access it. Follow How To Secure MongoDB on Ubuntu 20.04 to add an administrative user and lock things down further.

      Conclusion

      You can find more in-depth tutorials on how to configure and use MongoDB in these DigitalOcean community articles. The official MongoDB documentation is also a great resource on the possibilities that MongoDB provides.



      Source link

      Understanding Default Parameters in JavaScript


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

      In ECMAScript 2015, default function parameters were introduced to the JavaScript language. These allow developers to initialize a function with default values if the arguments are not supplied to the function call. Initializing function parameters in this way will make your functions easier to read and less error-prone, and will provide default behavior for your functions. This will help you avoid errors that stem from passing in undefined arguments and destructuring objects that don’t exist.

      In this article, you will review the difference between parameters and arguments, learn how to use default parameters in functions, see alternate ways to support default parameters, and learn what types of values and expressions can be used as default parameters. You will also run through examples that demonstrate how default parameters work in JavaScript.

      Arguments and Parameters

      Before explaining default function parameters, it is important to know what it is that parameters can default to. Because of this, we will first review the difference between arguments and parameters in a function. If you would like to learn more about this distinction, check out our earlier article in the JavaScript series, How to Define Functions in JavaScript.

      In the following code block, you will create a function that returns the cube of a given number, defined as x:

      // Define a function to cube a number
      function cube(x) {
        return x * x * x
      }
      

      The x variable in this example is a parameter—a named variable passed into a function. A parameter must always be contained in a variable and must never have a direct value.

      Now take a look at this next code block, which calls the cube function you just created:

      // Invoke cube function
      cube(10)
      

      This will give the following output:

      Output

      1000

      In this case, 10 is an argument—a value passed to a function when it is invoked. Often the value will be contained in a variable as well, such as in this next example:

      // Assign a number to a variable
      const number = 10
      
      // Invoke cube function
      cube(number)
      

      This will yield the same result:

      Output

      1000

      If you do not pass an argument to a function that expects one, the function will implicitly use undefined as the value:

      // Invoke the cube function without passing an argument
      cube()
      

      This will return:

      Output

      NaN

      In this case, cube() is trying to calculate the value of undefined * undefined * undefined, which results in NaN, or “not a number”. For more on this, take a look at the number section of Understanding Data Types in JavaScript.

      This automatic behavior can sometimes be a problem. In some cases, you might want the parameter to have a value even if no argument was passed to the function. That’s where the default parameters feature comes in handy, a topic that you will cover in the next section.

      Default Parameter Syntax

      With the addition of default parameters in ES2015, you can now assign a default value to any parameter, which the function will use instead of undefined when called without an argument. This section will first show you how to do this manually, and then will guide you through setting default parameters.

      Without default parameters, you would have to explicitly check for undefined values in order to set defaults, as is shown in this example:

      // Check for undefined manually
      function cube(x) {
        if (typeof x === 'undefined') {
          x = 5
        }
      
        return x * x * x
      }
      
      cube()
      

      This uses a conditional statement to check if the value has been automatically provided as undefined, then sets the value of x as 5. This will result in the following output:

      Output

      125

      In contrast, using default parameters accomplishes the same goal in much less code. You can set a default value to the parameter in cube by assigning it with the equality assignment operator (=), as highlighted here:

      // Define a cube function with a default value
      function cube(x = 5) {
        return x * x * x
      }
      

      Now when the cube function is invoked without an argument, it will assign 5 to x and return the calculation instead of NaN:

      // Invoke cube function without an argument
      cube()
      

      Output

      125

      It will still function as intended when an argument is passed, ignoring the default value:

      // Invoke cube function with an argument
      cube(2)
      

      Output

      8

      However, one important caveat to note is that the default parameter value will also override an explicit undefined passed as an argument to a function, as demonstrated here:

      // Invoke cube function with undefined
      cube(undefined)
      

      This will give the calculation with x equal to 5:

      Output

      125

      In this case, the default parameter values were calculated, and an explicit undefined value did not override them.

      Now that you have an idea of the basic syntax of default parameters, the next section will show how default parameters work with different data types.

      Default Parameter Data Types

      Any primitive value or object can be used as a default parameter value. In this section, you will see how this flexibility increases the ways in which default parameters can be used.

      First, set parameters using a number, string, boolean, object, array, and null value as a default value. This example will use arrow function syntax:

      // Create functions with a default value for each data type
      const defaultNumber = (number = 42) => console.log(number)
      const defaultString = (string = 'Shark') => console.log(string)
      const defaultBoolean = (boolean = true) => console.log(boolean)
      const defaultObject = (object = { id: 7 }) => console.log(object)
      const defaultArray = (array = [1, 2, 3]) => console.log(array)
      const defaultNull = (nullValue = null) => console.log(nullValue)
      

      When these functions are invoked without parameters, they will all use the default values:

      // Invoke each function
      defaultNumber()
      defaultString()
      defaultBoolean()
      defaultObject()
      defaultArray()
      defaultNull()
      

      Output

      42 "Shark" true {id: 7} (3) [1, 2, 3] null

      Note that any object created in a default parameter will be created every time the function is called. One of the common use cases for default parameters is to use this behavior to obtain values out of an object. If you try to destructure or access a value from an object that doesn’t exist, it will throw an error. However, if the default parameter is an empty object, it will simply give you undefined values instead of throwing an error:

      // Define a settings function with a default object
      function settings(options = {}) {
        const { theme, debug } = options
      
        // Do something with settings
      }
      

      This will avoid the error caused by destructuring objects that don’t exist.

      Now that you’ve seen how default parameters operate with different data types, the next section will explain how multiple default parameters can work together.

      Using Multiple Default Parameters

      You can use as many default parameters as you want in a function. This section will show you how to do this, and how to use it to manipulate the DOM in a real-world example.

      First, declare a sum() function with multiple default parameters:

      // Define a function to add two values
      function sum(a = 1, b = 2) {
        return a + b
      }
      
      sum()
      

      This will result in the following default calculation:

      Output

      3

      Additionally, the value used in a parameter can be used in any subsequent default parameter, from left to right. For example, this createUser function creates a user object userObj as the third parameter, and all the function itself does is return userObj with the first two parameters:

      // Define a function to create a user object using parameters
      function createUser(name, rank, userObj = { name, rank }) {
        return userObj
      }
      
      // Create user
      const user = createUser('Jean-Luc Picard', 'Captain')
      

      If you call user here, you will get the following:

      Output

      {name: "Jean-Luc Picard", rank: "Captain"}

      It is usually recommended to put all default parameters at the end of a list of parameters, so that you can easily leave off optional values. If you use a default parameter first, you will have to explicitly pass undefined to use the default value.

      Here is an example with the default parameter at the beginning of the list:

      // Define a function with a default parameter at the start of the list
      function defaultFirst(a = 1, b) {
        return a + b
      }
      

      When calling this function, you would have to call defaultFirst() with two arguments:

      defaultFirst(undefined, 2)
      

      This would give the following:

      Output

      3

      Here is an example with the default parameter at the end of the list:

      // Define a function with a default parameter at the end of the list
      function defaultLast(a, b = 1) {
        return a + b
      }
      
      defaultLast(2)
      

      This would yield the same value:

      Output

      3

      Both functions have the same result, but the one with the default value last allows a much cleaner function call.

      For a real-world example, here is a function that will create a DOM element, and add a text label and classes, if they exist.

      // Define function to create an element
      function createNewElement(tag, text, classNames = []) {
        const el = document.createElement(tag)
        el.textContent = text
      
        classNames.forEach(className => {
          el.classList.add(className)
        })
      
        return el
      }
      

      You can call the function with some classes in an array:

      const greeting = createNewElement('p', 'Hello!', ['greeting', 'active'])
      

      Calling greeting will give the following value:

      Output

      <p class="greeting active">Hello!</p>

      However, if you leave the classNames array out of the function call, it will still work.

      const greeting2 = createNewElement('p', 'Hello!')
      

      greeting2 now has the following value:

      Output

      <p>Hello!</p>

      In this example, forEach() can be used on an empty array without an issue. If that empty array were not set in the default parameter, you would get the following error:

      Output

      VM2673:5 Uncaught TypeError: Cannot read property 'forEach' of undefined at createNewElement (<anonymous>:5:14) at <anonymous>:12:18

      Now that you have seen how multiple default parameters can interact, you can move on to the next section to see how function calls work as default parameters.

      Function Calls as Default Parameters

      In addition to primitives and objects, the result of calling a function can be used as a default parameter.

      In this code block, you will create a function to return a random number, and then use the result as the default parameter value in a cube function:

      // Define a function to return a random number from 1 to 10
      function getRandomNumber() {
        return Math.floor(Math.random() * 10)
      }
      
      // Use the random number function as a default parameter for the cube function
      function cube(x = getRandomNumber()) {
        return x * x * x
      }
      

      Now invoking the cube function without a parameter will have potentially different results every time you call it:

      // Invoke cube function twice for two potentially different results
      cube()
      cube()
      

      The output from these function calls will vary:

      Output

      512 64

      You can even use built-in methods, like those on the Math object, and use the value returned in one function call as a parameter in another function.

      In the following example, a random number is assigned to x, which is used as the parameter in the cube function you created. The y parameter will then calculate the cube root of the number and check to see if x and y are equal:

      // Assign a random number to x
      // Assign the cube root of the result of the cube function and x to y
      function doesXEqualY(x = getRandomNumber(), y = Math.cbrt(cube(x))) {
        return x === y
      }
      
      doesXEqualY()
      

      This will give the following:

      Output

      true

      A default parameter can even be a function definition, as seen in this example, which defines a parameter as the inner function and returns the function call of parameter:

      // Define a function with a default parameter that is an anonymous function
      function outer(
        parameter = function inner() {
          return 100
        }
      ) {
        return parameter()
      }
      
      // Invoke outer function
      outer()
      

      Output

      100

      This inner function will be created from scratch every time the outer function is invoked.

      Conclusion

      In this article, you learned what default function parameters are and how to use them. Now you can use default parameters to help keep your functions clean and easy to read. You can also assign empty objects and arrays to parameters upfront to reduce both complexity and lines of code when dealing with situations such as retrieving values from an object or looping through an array.

      If you would like to learn more about JavaScript, check out the homepage for our How To Code in JavaScript series, or browse our How to Code in Node.js series for articles on back-end development.



      Source link