欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

[拉勾教育-大前端高薪训练营]ES2015 函数的参数默认值与剩余参数

程序员文章站 2022-07-16 14:38:43
...

参数默认值

ECMAScript2015 为函数的形参列表扩展了一些有用的新语法,其中一个叫做参数默认值。在 ECMAScript2015 之前要为函数中的参数定义默认值,需要在函数体中通过逻辑代码来实现。如下代码所示:

function foo(enable) {
  enable = enable || true
  console.log(`foo invoked - enable: ${enable}`)
}

foo()

这里存在一个很多人经常犯错误的地方,就是很喜欢使用短路运算的方式来设置参数的默认值。实际上,这里是不能使用短路运算来设置参数的默认值的。因为使用短路运算设置参数的默认值,导致如果传递 false 也会使用默认值。如下代码所示:

function foo(enable) {
  enable = enable || true
  console.log(`foo invoked - enable: ${enable}`)
}

foo(false)

上述代码的运行结果如下:

foo invoked - enable: true

而正确地为参数设置默认值的方式,应该是判断参数的值是否等于 undefined。如下代码所示:

function foo(enable) {
  enable = enable === undefined ? true : enable
  console.log(`foo invoked - enable: ${enable}`)
}

foo(false)

因为参数默认值的定义就是在没有传递实参时所使用的值,而没有传递实参所得到的应该是 undefined,所以这里应该是判断参数的值是否等于 undefined

不过在 ECMAScript2015 新增了参数的默认值之后,这一切就变得简单得多。如下代码所示:

function foo(enable = true) {
  console.log(`foo invoked - enable: ${enable}`)
}

foo(false)

这里只需要在函数的形参位置直接定义该参数的默认值即可。这个默认值只有在调用函数时没有传递实参或者实参的值为 undefined 时才会被使用。

需要注意的是,如果一个函数具有多个参数的话,那带有默认值的参数一定要在参数列表的最后,因为参数是按照次序进行传递的。如下代码所示:

function foo(enable = true, bar) {
  console.log(`foo invoked - enable: ${enable}`)
  console.log(`foo invoked - bar: ${bar}`)
}

foo()

上述代码的运行结果如下:

foo invoked - enable: true
foo invoked - bar: undefined

但如果调用 foo 函数时传递一个实参,这时的运行结果如下:

foo invoked - enable: false
foo invoked - bar: undefined

通过这样的测试会发现,如果带有默认值的参数没有定义在参数列表的最后的话,会导致参数的默认值无法正常工作。所以,带有默认值的参数一定要在参数列表的最后。如下代码所示:

function foo(bar, enable = true) {
  console.log(`foo invoked - bar: ${bar}`)
  console.log(`foo invoked - enable: ${enable}`)
}

foo(false)

上述代码的运行结果如下:

foo invoked - bar: false
foo invoked - enable: true

剩余参数

在 ECMAScript 中很多函数或方法都允许传递任意个数的参数,比如 consolelog() 方法允许接收任意个数的参数。如下代码所示:

console.log(1, 2, 3)

对于未知个数的参数,在 ECMAScript2015 之前都是使用 arguments 对象来接收。如下代码所示:

function foo() {
  console.log(arguments)
}

foo(1, 2, 3)

上述代码的运行结果如下:

{ '0': 1, '1': 2, '2': 3 }

arguments 对象实际上是一个伪数组对象。ECMAScript2015 新增了剩余参数,以 ... 为前缀的。如下代码所示:

function foo(...args) {
  console.log(args)
}

foo(1, 2, 3)

上述代码的运行结果如下:

[ 1, 2, 3 ]

从上述运行的结果可以看到,剩余参数这种用法得到的是一个真实的数组,可以接收从当前位置开始到参数列表最后的所有实参。

需要注意的是,这种用法只能出现在参数列表的最后,而且只能使用一次。如下代码所示:

function foo(first, ...args) {
  console.log(args)
}

foo(1, 2, 3)

上述代码的运行结果如下:

[ 2, 3 ]

如果剩余参数的位置不是在参数列表的最后,将会报错。如下代码所示:

function foo(...args, last) {
  console.log(args)
}

foo(1, 2, 3)

上述代码的运行结果如下:

rest-parameter.js:19
function foo(...args, last) {
                    ^

SyntaxError: Rest parameter must be last formal parameter
    at createScript (vm.js:80:10)
    at Object.runInThisContext (vm.js:139:10)
    at Module._compile (module.js:599:28)
    at Object.Module._extensions..js (module.js:646:10)
    at Module.load (module.js:554:32)
    at tryModuleLoad (module.js:497:12)
    at Function.Module._load (module.js:489:3)
    at Function.Module.runMain (module.js:676:10)
    at startup (bootstrap_node.js:187:16)
    at bootstrap_node.js:608:3

如果剩余参数使用多次的话,也会报出与上述结果一样的错误。

展开数组

... 除了可以作为函数的剩余参数的 Rest 用法,还有一种用来展开的 Spread 用法。展开这种用法的用途有很多,这里先来掌握与函数相关的数组参数展开。

比如定义一个数组,通过 console.log() 方法依次打印这个数组中的成员。那最笨的方法就是通过索引值访问数组中的每一个成员。如下代码所示:

const arr = ['foo', 'bar', 'baz']

console.log(arr[0], arr[1], arr[2])

如果数组中成员的个数是不固定的话,这样通过索引值访问数组中所有的成员这种方式就行不通了。在 ECMAScript2015 之前通常是通过 apply() 方法来解决这个问题。如下代码所示:

const arr = ['foo', 'bar', 'baz']

console.log.apply(console, arr)

ECMAScript2015 之后就可以使用 ... 用法来展开数组,从而得到数组中每一个成员。如下代码所示:

const arr = ['foo', 'bar', 'baz']

console.log(...arr)

这种方式会将数组中的成员按照次序传递给函数。