在 ES6 中,函数默认值是一个十分常用的特性。它可以为函数的参数指定默认值,从而使得在调用函数时可以不传递该参数,而直接使用默认值。然而,使用函数默认值也会带来一些困扰,本文将介绍这些困扰以及如何进行优化。
困扰
默认值不生效
当使用函数默认值时,我们可能会遇到默认值不生效的情况。例如:
function foo(a = 1) { console.log(a); } foo(undefined); // 1 foo(null); // null
在上面的例子中,我们传递了 undefined
和 null
作为参数,但是函数的默认值并没有生效。这是因为在函数调用时,只有当参数的值为 undefined
时,才会使用默认值。而当参数的值为 null
时,默认值并不会生效。
默认值共享
当函数的默认值是一个对象或数组时,我们可能会遇到默认值共享的情况。例如:
function foo(a = []) { a.push(1); console.log(a); } foo(); // [1] foo(); // [1, 1]
在上面的例子中,我们每次调用函数时都会向默认值 []
中添加一个元素。但是,由于默认值是在函数定义时就被创建的,所以每次调用函数时都会使用同一个默认值,导致元素不断地被添加进去。
作用域问题
当函数的默认值是一个函数调用或表达式时,我们可能会遇到作用域问题。例如:
-- -------------------- ---- ------- --- - - -- -------- ----- - -- - --------------- - ------ -- - - - -- ------ -- -
在上面的例子中,我们使用变量 x
作为函数的默认值。然而,由于默认值是在函数定义时就被创建的,所以它使用的是函数定义时的作用域,而不是函数调用时的作用域。因此,即使我们在调用函数之前改变了变量 x
的值,函数的默认值也不会受到影响。
优化
使用函数参数
为了避免默认值不生效的问题,我们可以使用函数参数来判断是否传递了参数。例如:
function foo(a) { a = (a === undefined) ? 1 : a; console.log(a); } foo(undefined); // 1 foo(null); // null
在上面的例子中,我们首先判断参数 a
是否为 undefined
,如果是则使用默认值 1
,否则使用传递的参数。
使用函数参数和短路运算符
为了避免默认值共享的问题,我们可以使用函数参数和短路运算符来创建一个新的默认值。例如:
function foo(a = []) { a = (a instanceof Array) ? a : []; a.push(1); console.log(a); } foo(); // [1] foo(); // [1]
在上面的例子中,我们首先判断参数 a
是否为数组,如果是则使用传递的数组,否则创建一个新的空数组。这样就可以避免默认值共享的问题。
使用函数参数和闭包
为了避免作用域问题,我们可以使用函数参数和闭包来创建一个新的默认值。例如:
-- -------------------- ---- ------- -------- ----- - ----------- - ------ -- ----- - --------------- - --- - - -- ------ -- - - - -- ------ -- -
在上面的例子中,我们使用一个立即执行的函数来返回变量 x
的值。由于该函数是在函数调用时执行的,所以它使用的是函数调用时的作用域,而不是函数定义时的作用域。这样就可以避免作用域问题。
结论
函数默认值是一个常用的特性,但是它也会带来一些困扰。为了避免这些困扰,我们可以使用函数参数、短路运算符和闭包来进行优化。在使用函数默认值时,需要注意默认值不生效、默认值共享和作用域问题。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/6754fb101b963fe9cc516119