核心要点
创建方法也意味着编写 API——无论是为您自己、团队中的其他开发人员还是使用您项目的其他开发人员。根据函数的大小、复杂性和用途,您必须考虑默认设置和输入/输出的 API。默认函数参数和属性简写是 ES6 的两个方便的功能,可以帮助您编写 API。
ES6 默认参数
让我们快速回顾一下知识,再看看语法。默认参数允许我们为函数初始化默认值。当参数被省略或未定义时使用默认值——这意味着 null 是一个有效值。默认参数可以是任何东西,从数字到另一个函数。
<code class="language-javascript">// 基本语法 function multiply(a, b = 2) { return a * b; } multiply(5); // 10 // 默认参数也适用于后面的默认参数 function foo(num = 1, multi = multiply(num)) { return [num, multi]; } foo(); // [1, 2] foo(6); // [6, 12]</code>
让我们来看一个基本函数,并演示默认参数如何加快您的开发速度并使代码组织得更好。我们的示例方法称为 createElement()。它接受一些配置参数,并返回一个 HTML 元素。API 看起来像这样:
<code class="language-javascript">// 我们想要一个 <p> 元素,带有一些文本内容和两个附加的类。 // 返回 </p> <p>Such unique text</p> createElement('p', { content: 'Such unique text', classNames: ['very-special-text', 'super-big'] }); // 为了使此方法更有用,它应该在任何参数被省略或根本没有传递参数时始终返回默认元素。 createElement(); // <div>Very default</div></code>
此方法的实现不会有很多逻辑,但由于其默认覆盖范围,它可能会变得相当大。
<code class="language-javascript">// 没有默认参数,它看起来相当臃肿且不必要地庞大。 function createElement(tag, config) { tag = tag || 'div'; config = config || {}; const element = document.createElement(tag); const content = config.content || 'Very default'; const text = document.createTextNode(content); let classNames = config.classNames; if (classNames === undefined) { classNames = ['module-text', 'default']; } element.classList.add(...classNames); element.appendChild(text); return element; }</code>
到目前为止,一切顺利。这里发生了什么?我们正在执行以下操作:
现在让我们使用此函数并对其进行优化,使其更简洁、编写速度更快,并且更清晰地表明其用途:
<code class="language-javascript">// 基本语法 function multiply(a, b = 2) { return a * b; } multiply(5); // 10 // 默认参数也适用于后面的默认参数 function foo(num = 1, multi = multiply(num)) { return [num, multi]; } foo(); // [1, 2] foo(6); // [6, 12]</code>
我们没有触及函数的逻辑,而是从函数体中删除了所有默认处理。函数签名现在包含所有默认值。让我进一步解释一部分,这可能有点令人困惑:
<code class="language-javascript">// 我们想要一个 <p> 元素,带有一些文本内容和两个附加的类。 // 返回 </p> <p>Such unique text</p> createElement('p', { content: 'Such unique text', classNames: ['very-special-text', 'super-big'] }); // 为了使此方法更有用,它应该在任何参数被省略或根本没有传递参数时始终返回默认元素。 createElement(); // <div>Very default</div></code>
我们不仅声明了一个默认对象参数,还声明了默认对象属性。这使得默认配置看起来更清晰,而不是只声明一个默认对象(例如 config = {})然后稍后设置默认属性。可能需要一些额外的时间来适应它,但最终它会改善您的工作流程。当然,对于更大的配置,我们仍然可以争论说它可能会创建更多开销,并且只需将默认处理保留在函数体中会更简单。
ES6 属性简写
如果方法接受大型配置对象作为参数,则您的代码可能会变得相当大。通常的做法是准备一些变量并将它们添加到该对象中。属性简写是语法糖,可以使此步骤更短、更易读:
<code class="language-javascript">// 没有默认参数,它看起来相当臃肿且不必要地庞大。 function createElement(tag, config) { tag = tag || 'div'; config = config || {}; const element = document.createElement(tag); const content = config.content || 'Very default'; const text = document.createTextNode(content); let classNames = config.classNames; if (classNames === undefined) { classNames = ['module-text', 'default']; } element.classList.add(...classNames); element.appendChild(text); return element; }</code>
好的,让我们回到另一个更常见的例子。以下函数获取一些数据,对其进行修改并调用另一个方法:
<code class="language-javascript">// 默认所有内容 function createElement(tag = 'div', { content = 'Very default', classNames = ['module-text', 'special'] } = {}) { const element = document.createElement(tag); const text = document.createTextNode(content); element.classList.add(...classNames); element.appendChild(text); return element; }</code>
我们经常会将变量和对象属性名称命名为相同。使用属性简写结合解构,我们实际上可以缩短代码很多:
<code class="language-javascript">// 这里到底发生了什么? function createElement({ content = 'Very default', classNames = ['module-text', 'special'] } = {}) { // 函数体 }</code>
同样,这可能需要一段时间才能适应。最终,它是 JavaScript 中的新功能之一,它帮助我更快地编写代码并使用更简洁的函数体。但是等等,还有更多!属性简写还可以应用于对象内的使用方法定义:
<code class="language-javascript">const a = 'foo', b = 42, c = function() {}; // 以前我们会像这样使用这些常量。 const alphabet = { a: a, b: b, c: c }; // 但是使用新的简写,我们现在实际上可以这样做, // 这与上面相同。 const alphabet = {a, b, c};</code>
结论
默认参数和属性简写是使您的方法更井然有序,在某些情况下甚至更短的好方法。总的来说,默认函数参数帮助我更专注于方法的实际用途,而不会因大量的默认准备工作和 if 语句而分心。属性简写确实更多的是一种外观上的特性,但我发现自己生产力更高,并且花费更少的时间来编写所有变量、配置对象和函数关键字。您是否已经在使用默认参数和属性简写?本文由 Sebastian Seitz 进行了同行评审。感谢所有 SitePoint 的同行评审者,使 SitePoint 内容尽善尽美!
关于 ES6 默认参数的常见问题 (FAQ)
ES6 默认参数提供了多个优势。首先,它们有助于使您的代码更简洁易读。无需检查参数是否未定义,然后分配默认值,您可以在一行中完成所有操作。这减少了您必须编写的代码量,并使其他人更容易理解您的代码。其次,它们有助于防止错误。如果函数期望某个参数但未提供,则可能导致意外结果或错误。通过设置默认参数,您可以确保您的函数拥有其正常工作所需的所有参数。
是的,您可以将 ES6 默认参数与解构赋值一起使用。这是 ES6 的一个强大功能,它允许您将数组中的值或对象中的属性解包到不同的变量中。与默认参数结合使用时,您可以从对象或数组中提取值,并在提取的值未定义时分配默认值。
arguments 对象是一个类似数组的对象,其中包含传递给函数的所有参数。但是,它并非拥有数组的所有方法,并且不如 ES6 默认参数功能灵活。使用默认参数,您可以为任何未定义的参数设置默认值,而这在 arguments 对象中是不可能的。
是的,您可以在构造函数中使用 ES6 默认参数。在创建类的新的实例时,这尤其有用。如果在创建新实例时未提供某些参数,则将使用默认参数,以确保新对象具有所有必要的属性。
一般来说,使用 ES6 默认参数的性能影响很小,不应成为问题。但是,像任何功能一样,应该谨慎使用它。过度使用默认参数,尤其是在性能关键的代码中,可能会导致执行时间变慢。与往常一样,务必测试您的代码并监控其性能。
是的,您可以将 ES6 默认参数与箭头函数一起使用。ES6 中引入的箭头函数提供了一种简洁的语法来编写函数表达式。在使用将其他函数作为参数的高阶函数时,它们尤其有用。
如果参数传递了 null 值,则 ES6 默认参数功能将不会分配默认值。这是因为 null 在 JavaScript 中被认为是一个值,与 undefined 不同。如果要在参数为 null 时分配默认值,则需要在代码中单独处理这种情况。
是的,您可以在递归函数中使用 ES6 默认参数。当您想要为递归函数提供基本情况但又不想要求调用者始终提供它时,这尤其有用。
是的,您可以将 ES6 默认参数与剩余参数一起使用。但是,请记住,剩余参数必须是函数定义中的最后一个参数。此外,您不能为剩余参数本身分配默认值,但可以为剩余参数的一部分的各个参数分配默认值。
是的,您可以将 ES6 默认参数与扩展运算符一起使用。扩展运算符允许您将可迭代对象(如数组)扩展为各个元素。与默认参数结合使用时,您可以将一组值传递给函数,并为任何未定义的参数分配默认值。
以上是带有ES6默认参数和属性速记的清洁代码的详细内容。更多信息请关注PHP中文网其他相关文章!