从 ECMAScript 2021 开始,函数参数默认值的设置方式有了一些变化,然而这也可能导致一些问题。本文将探讨在 JavaScript 中如何解决这些问题,并提供一些示例代码和指导意义。
问题描述
在 ECMAScript 2021 中,函数参数的默认值可以通过两种方式来设置。第一种是使用 "=" 符号设置参数的默认值,如下所示:
function greet(name = 'World') { console.log('Hello, ' + name + '!'); }
第二种是使用双重否定符号 "!!" 来设置参数的默认值,如下所示:
function greet(name) { name = name ?? 'World'; console.log('Hello, ' + name + '!'); }
这些方法在大多数情况下都可以很好地工作,但是它们也可能会引起一些问题。
值的判断
首先,我们来看一个问题:如果函数的参数默认值是一个空数组 [] 或空对象 {},则不能像预期的那样进行值的判断。
-- -------------------- ---- ------- -------- ------- - --- - -- ----- - ---------------- ----- -- --- -------- - ---- - ---------------- ----- -- -------- - - ------ -- -- ---- ----- -- --- -------
上面的代码输出 "The array is not empty.",这是因为数组 [] 实际上是一个真值(truthy),并且在 if 语句中会自动转换为布尔值 true。
因此,为了避免这种问题,我们可以使用 typeof 来判断参数的类型是否为 undefined:
-- -------------------- ---- ------- -------- -------- - --- - --- --- --------- - -- - ---- -- ------------ - ---------------- ----- -- --- -------- - ---- - ---------------- ----- -- -------- - - ------ -- -- ---- ----- -- -------
参数名的使用
第二个问题与参数名的使用有关。在使用双重否定符号来设置参数的默认值时,如果使用参数名来进行判断,则会引发参数名未定义(ReferenceError)的问题。
function foo(name) { name = name ?? name; // 报错:Cannot access 'name' before initialization console.log('Hello, ' + name + '!'); }
这是因为在执行函数时,参数名还未被初始化,因此无法使用。解决此问题的方法是在函数开头手动去定义参数名。
function foo(name) { let newName = name ?? 'World'; console.log('Hello, ' + newName + '!'); }
对象字面量的作用域
第三个问题与对象字面量的作用域(scope)有关。在使用对象字面量作为函数参数默认值时,对象字面量中的属性只能访问函数作用域中的变量,而不能访问对象字面量的属性。
let prefix = 'Hello'; function foo({ name = 'World', message = prefix + ',' } = {}) { console.log(message + ' ' + name + '!'); } foo({ name: 'John' }); // 输出 "undefined John!"
在上面的代码中,我们期望把 message 的默认值设置为 'Hello,',但是输出的结果是 "undefined John!"。这是因为在对象字面量中,prefix 变量不是函数作用域中的变量,因此不能被访问。解决此问题的方法是使用函数作用域中的变量来代替对象字面量中的属性。
let prefix = 'Hello'; function foo({ name = 'World', message } = { message: prefix + ',' }) { message = message ?? prefix + ','; console.log(message + ' ' + name + '!'); } foo({ name: 'John' }); // 输出 "Hello, John!"
在上面的代码中,我们使用了 message ?? prefix + ',' 来判断参数是否有传入 message 属性,如果没有,则使用 prefix 变量来代替。
结论
在 ECMAScript 2021 中,函数参数默认值的设置方式有了一些变化,需要注意其中可能会引发的问题。在实际开发中,我们应该对参数的类型和作用域进行认真的考虑,并且考虑到一些可能出现的问题。在本文中,我们提供了解决这些问题的方法和示例代码,希望对您有所帮助。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/670cd7845f551281025bd30d