一句话总结:强烈建议掌握!函数参数默认值和属性速记(shorthands)减少了重复代码,降低了无意的工作量,使代码更清晰。
创建方法还意味着编写API —— 无论是为自己,团队中的其他开发人员,还是其他使用你项目的开发人员。根据功能的大小,复杂性和用途,你必须考虑默认设置和输入/输出的API。
默认函数参数和属性shorthands是ES6的两个便捷功能,可以帮助你编写API。
ES6默认参数
让我们快速了解我们的知识并再次查看语法。默认参数允许我们使用默认值初始化函数。当省略参数或者undefined时,参数设置为null。默认参数可以是从数字到另一个函数的任何内容。
// Basic syntax
function multiply (a, b = 2) {
return a * b;
}
multiply(5); // 10
// Default parameters are also available to later default parameters
function foo (num = 1, multi = multiply(num)) {
return [num, multi];
}
foo(); // [1, 2]
foo(6); // [6, 12]
一个现实世界的例子
让我们来看一个基本功能,并演示默认参数如何加速你的开发并使代码更有条理。
我们的示例方法叫做createElement()。它需要一些配置参数,并返回一个HTML元素。API看起来像这样:
// We want a <p> element, with some text content and two classes attached.
// Returns <p class="very-special-text super-big">Such unique text</p>
createElement('p', {
content: 'Such unique text',
classNames: ['very-special-text', 'super-big']
});
// To make this method even more useful, it should always return a default
// element when any argument is left out or none are passed at all.
createElement(); // <div class="module-text default">Very default</div>
这个实现没有太多逻辑,但由于它的默认值覆盖范围,代码可能会变得非常大。
// Without default parameters it looks quite bloated and unnecessary large.
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;
}
到现在为止还挺好。这里发生了什么事?我们正在做以下事情:
- 如果
tag
和config
没有被传递,为我们的参数设置默认值 - 使用实际内容(和默认值)创建常量
- 检查是否
classNames
已定义,如果没有则指定默认数组 - 在返回之前创建和修改元素。
现在让我们优化一下这个函数的写法:
// Default all the things
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;
}
我们没有触及函数的逻辑,但从函数体中删除了所有默认处理。该函数签名现在包含所有默认值。
让我进一步解释一个可能有点令人困惑的部分:
// What exactly happens here?
function createElement ({
content = 'Very default',
classNames = ['module-text', 'special']
} = {}) {
// function body
}
我们不仅声明默认object参数,还声明默认对象属性。这使得默认配置看起来更加明显,而不是仅声明默认对象(例如config = {})以及稍后设置默认属性。你可能需要一些额外的时间来适应它,但最终它会改善你的工作流程。
ES6属性速写(shorthand)
如果函数需要接受大型配置对象作为参数,则代码可能会变得非常大。准备一些变量并将它们添加到这个对象是很常见的。属性简写是语法糖,使这一步骤更短,更易读:
const a = 'foo', b = 42, c = function () {};
// Previously we would use these constants like this.
const alphabet = {
a: a,
b: b,
c: c
};
// But with the new shorthand we can actually do this now,
// which is equivalent to the above.
const alphabet = { a, b, c };
缩短API
好的,回到另一个更常见的例子。以下函数获取一些数据,对其进行变异并调用另一个方法:
function updateSomething (data = {}) {
const target = data.target;
const veryLongProperty = data.veryLongProperty;
let willChange = data.willChange;
if (willChange === 'unwantedValue') {
willChange = 'wayBetter';
}
// Do more.
useDataSomewhereElse({
target: target,
property: veryLongProperty,
willChange: willChange,
// .. more
});
}
通常我们将变量命名为和对象属性名称相同的名称。使用属性简写,结合解构,我们实际上可以缩短我们的代码:
function updateSomething (data = {}) {
// 从data对象中解构出常量,而且重新命名veryLongProperty
const { target, veryLongProperty: property } = data;
let { willChange } = data;
if (willChange === 'unwantedValue') {
willChange = 'wayBetter';
}
// Do more.
useDataSomewhereElse({ target, property, willChange });
}
同样,这可能需要一段时间才能习惯。最后,它是JavaScript中的一个新功能,它帮助我更快地编写代码并使用更清晰的函数体。
但等等,还有更多!属性简写也可以应用于对象内的方法定义:
// 声明方法时需要使用function关键字
const module = {
foo: 42,
bar: function (value) {
// do something
}
};
// 缩短bar方法的声明
const module = {
foo: 42,
bar (value) {
// do something
}
};
结论
默认参数和属性简写是使函数更有条理的好方法,在某些情况下甚至更短。总的来说,默认函数参数帮助我更多地关注方法的实际目的,而不会分散大量的默认准备和if语句。
属性shorthands
确实更像是一种装饰性功能,但我发现自己的工作效率更高,并且花费更少的时间来编写所有变量,配置对象和function关键字。
网友评论