了解JavaScript中的默认参数

来自菜鸟教程
跳转至:导航、​搜索

作者选择了 COVID-19 Relief Fund 作为 Write for DOnations 计划的一部分来接受捐赠。

介绍

ECMAScript 2015中,默认函数参数被引入JavaScript语言。 如果参数未提供给函数调用,这些允许开发人员使用默认值初始化 函数。 以这种方式初始化函数参数将使您的函数更易于阅读且不易出错,并将为您的函数提供默认行为。 这将帮助您避免因传入 undefined 参数和解构不存在的对象而产生的错误。

在本文中,您将回顾参数和实参之间的区别,了解如何在函数中使用默认参数,查看支持默认参数的替代方法,并了解哪些类型的值和表达式可以用作默认参数。 您还将通过示例演示默认参数如何在 JavaScript 中工作。

参数和参数

在解释默认函数参数之前,重要的是要知道参数可以默认为什么。 因此,我们将首先回顾一下函数中argumentsparameters之间的区别。 如果您想了解有关此区别的更多信息,请查看我们在 JavaScript 系列如何在 JavaScript 中定义函数 中的早期文章。

在下面的代码块中,您将创建一个返回给定数字的立方体的函数,定义为 x

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

此示例中的 x 变量是 参数 — 传递给函数的命名变量。 参数必须始终包含在变量中,并且绝不能有直接值。

现在看看下一个代码块,它调用了您刚刚创建的 cube 函数:

// Invoke cube function
cube(10)

这将给出以下输出:

Output1000

在这种情况下,10 是一个 参数 — 一个在调用函数时传递给函数的值。 通常该值也将包含在变量中,例如在下一个示例中:

// Assign a number to a variable
const number = 10

// Invoke cube function
cube(number)

这将产生相同的结果:

Output1000

如果您不将参数传递给需要一个参数的函数,则该函数将隐式使用 undefined 作为值:

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

这将返回:

OutputNaN

在这种情况下,cube() 试图计算 undefined * undefined * undefined 的值,结果是 NaN 或“不是数字”。 有关这方面的更多信息,请查看 Understanding Data Types in JavaScript 的数字部分。

这种自动行为有时会成为问题。 在某些情况下,您可能希望参数具有值,即使没有参数传递给函数。 这就是 默认参数 功能派上用场的地方,您将在下一节中介绍这个主题。

默认参数语法

通过在 ES2015 中添加默认参数,您现在可以为任何参数分配一个默认值,该函数将在不带参数的情况下调用该函数而不是 undefined。 本节将首先向您展示如何手动执行此操作,然后将指导您设置默认参数。

如果没有默认参数,您必须显式检查 undefined 值才能设置默认值,如下例所示:

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

  return x * x * x
}

cube()

这使用 条件语句 来检查值是否已自动提供为 undefined,然后将 x 的值设置为 5。 这将导致以下输出:

Output125

相比之下,使用默认参数可以用更少的代码实现相同的目标。 您可以使用等式赋值运算符 (=) 为 cube 中的参数设置默认值,如下所示:

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

现在当 cube 函数在没有参数的情况下被调用时,它会将 5 分配给 x 并返回计算而不是 NaN

// Invoke cube function without an argument
cube()
Output125

传递参数时,它仍将按预期运行,忽略默认值:

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

但是,需要注意的一个重要警告是,默认参数值还将覆盖作为参数传递给函数的显式 undefined,如下所示:

// Invoke cube function with undefined
cube(undefined)

这将给出 x 等于 5 的计算:

Output125

在这种情况下,计算了默认参数值,并且明确的 undefined 值不会覆盖它们。

现在您已经了解了默认参数的基本语法,下一节将展示默认参数如何处理不同的数据类型。

默认参数数据类型

任何 原始值对象 都可以用作默认参数值。 在本节中,您将看到这种灵活性如何增加默认参数的使用方式。

首先,使用 numberstringboolean、object、array 和 null 值作为默认值设置参数。 此示例将使用 箭头函数 语法:

// 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)

当这些函数在没有参数的情况下被调用时,它们都将使用默认值:

// Invoke each function
defaultNumber()
defaultString()
defaultBoolean()
defaultObject()
defaultArray()
defaultNull()
Output42
"Shark"
true
{id: 7}
(3) [1, 2, 3]
null

请注意,每次调用函数时都会创建在默认参数中创建的任何对象。 默认参数的常见用例之一是使用此行为从对象中获取值。 如果您尝试从不存在的对象中解构或访问值,则会引发错误。 但是,如果默认参数是一个空对象,它只会给你 undefined 值而不是抛出错误:

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

  // Do something with settings
}

这将避免因解构不存在的对象而导致的错误。

现在您已经了解了默认参数如何处理不同的数据类型,下一节将解释多个默认参数如何协同工作。

使用多个默认参数

您可以在函数中使用任意数量的默认参数。 本节将向您展示如何执行此操作,以及如何在实际示例中使用它来操作 DOM

首先,声明一个带有多个默认参数的 sum() 函数:

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

sum()

这将导致以下默认计算:

Output3

此外,参数中使用的值可以在任何后续默认参数中使用,从左到右。 例如,这个 createUser 函数创建一个用户对象 userObj 作为第三个参数,而函数本身所做的只是返回带有前两个参数的 userObj

// 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')

如果你在这里调用 user,你会得到以下信息:

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

通常建议将所有默认参数放在参数列表的末尾,以便您可以轻松地省略可选值。 如果首先使用默认参数,则必须显式传递 undefined 才能使用默认值。

这是一个在列表开头使用默认参数的示例:

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

调用此函数时,您必须使用两个参数调用 defaultFirst()

defaultFirst(undefined, 2)

这将给出以下内容:

Output3

这是列表末尾带有默认参数的示例:

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

defaultLast(2)

这将产生相同的值:

Output3

这两个函数具有相同的结果,但最后一个具有默认值的函数允许更清晰的函数调用。

对于一个真实的例子,这里有一个函数,它将创建一个 DOM 元素,并添加一个文本标签和类(如果它们存在)。

// 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
}

您可以使用数组中的某些类调用该函数:

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

调用 greeting 将给出以下值:

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

但是,如果您将 classNames 数组排除在函数调用之外,它仍然可以工作。

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

greeting2 现在具有以下值:

Output<p>Hello!</p>

在此示例中, forEach() 可以毫无问题地用于空数组。 如果该空数组未在默认参数中设置,您将收到以下错误:

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

现在您已经了解了多个默认参数如何交互,您可以继续下一节了解函数调用如何作为默认参数工作。

函数调用作为默认参数

除了原语和对象外,调用函数的结果也可以用作默认参数。

在此代码块中,您将创建一个返回随机数的函数,然后将结果用作 cube 函数中的默认参数值:

// 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
}

现在调用不带参数的 cube 函数每次调用它时可能会产生不同的结果:

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

这些函数调用的输出会有所不同:

Output512
64

您甚至可以使用内置方法,例如 Math 对象上的方法,并将一个函数调用中返回的值用作另一个函数的参数。

在以下示例中,将一个随机数分配给 x,用作您创建的 cube 函数中的参数。 然后 y 参数将计算数字的立方根并检查 xy 是否相等:

// 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()

这将给出以下内容:

Outputtrue

默认参数甚至可以是函数定义,如本例所示,它将参数定义为 inner 函数并返回 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()
Output100

每次调用 outer 函数时,都会从头开始创建此 inner 函数。

结论

在本文中,您了解了默认函数参数是什么以及如何使用它们。 现在,您可以使用默认参数来帮助保持函数简洁易读。 您还可以预先将空对象和数组分配给参数,以在处理从对象中检索值或循环遍历数组等情况时减少复杂性和代码行数。

如果您想了解更多关于 JavaScript 的知识,请查看我们的主页以查看我们的 如何在 JavaScript 中编写代码系列,或者浏览我们的 如何在 Node.js 中编写代码系列 以获取后面的文章-结束开发。