使用 JavaScript 中的解构提取函数参数
使用 JavaScript 中的解构提取函数参数
使用 JavaScript 中的解构提取函数参数
ES6 解构非常擅长从参数中提取值。所以下次看到数组括号符号时,只需将其替换掉,并使用解构语法即可。
function omelette(...args) {
// ❌ Old Way
const egg = args[0];
const cheese = args[1];
// ✅ Better Way with Destructuring
const [egg, cheese] = args;
}
omelette('🥚', '🧀');
分解代码
我们要做的第一件事是将所有参数收集到一个数组中。
// Step 1:
(...args)
args // [ '🥚', '🧀' ]
接下来,我们使用数组解构将它们分配给我们的变量。
// Step 2:
const [egg, cheese] = args;
egg; // '🥚'
cheese; // '🧀'
理解arguments
对象
语法上有些令人困惑。我认为这是因为参数对象。所以我会尝试解释一下。每个函数都有一个内置arguments
对象。该arguments
对象是一个类似数组的对象,对应于传递给函数的参数。
function omelette() {
console.log(arguments); // { 0: '🥚', 1: '🧀' }
}
omelette('🥚', '🧀');
☝️如你所见,它arguments
不是一个数组。它是一个类似数组的对象。要将其转换为真正的数组,我可以使用...
展开语法。
function omelette() {
var args = [...arguments];
console.log(args); // [ '🥚', '🧀' ]
}
omelette('🥚', '🧀');
注意,我的函数不接受任何参数,但我的arguments
对象却存在。我知道这有点让人困惑,因为我把它命名为args
。所以,让我们更清楚地了解一下,看看哪个函数传入了参数,哪个函数传入了arguments
对象。
function food(egg) {
egg; // '🥚'
arguments; // { 0: '🥚', 1: '🚕' }
}
food('🥚', '🚕');
术语“参数”与“实参”
我一直以为这些术语可以互换。后来我意识到它们之间存在语言差异。
参数:是函数声明中的变量。创建函数时,它是函数签名的一部分。
用一句话来说,我会说:“这个函数正在接受name
参数”
function sayHi(name) {
// 👈 parameter
}
参数:是调用函数时传递给函数的变量的实际值。
用一句话来表达,我会说:“我正在传递samantha
这个函数”
sayHi('samantha'); // 👈 argument
我的记忆是这样的。Parameter 中的“P”代表函数声明中的P占位符。Argument 中的“A”代表函数的实际值。
剩余参数 vs 参数对象
让我们首先解释一下什么是 Rest 参数:
剩余参数语法允许我们将不确定数量的参数表示为数组。
Rest 参数收集传递给函数的各个参数并返回一个数组
function cook(...ingredients) { // 👈 Have to accept the parameters
return ingredients;
// [ '🧈', '🥓' ] 👈 Returns an array
}
cook('🧈', '🥓'); // 👈 Passing the arguments
然而,这与对象不同arguments
。注意,我不需要将参数传递到参数中。JavaScript 中创建的每个非箭头函数都有一个本地arguments
对象。这也是为什么你不想使用 using 命名的原因,arguments
因为你会覆盖它。
function cook() { // 👈 NOT accepting any parameters
return arguments;
// { '0': '🧈', '1': '🥓' } 👈 Returns an "arguments" object
}
cook('🧈', '🥓'); // 👈 Passing the arguments
最佳实践是避免使用arguments
对象,而应使用剩余参数。这就是 ES6 引入剩余参数的原因,它使需要访问和处理无限量参数的 JavaScript 开发人员更加轻松。
论证最佳实践
AirBnb 的 JavaScript 样式指南中指出了使用函数参数的一些最佳实践:
切勿将参数命名为arguments。这将优先于每个函数作用域中传入的arguments对象。
// bad
function foo(name, options, arguments) {
// ...
}
// good
function foo(name, options, args) {
// ...
}
永远不要使用参数,而选择使用 rest 语法...
为什么?...
明确说明了要提取哪些参数。此外,剩余参数是真正的数组,而不仅仅是类似数组的参数。
// bad
function foo() {
const args = Array.prototype.slice.call(arguments);
}
// good
function foo(...args) {
}
社区意见
设置默认值
@lukeshiru:您甚至可以在标题中设置默认值。
function omelette(...[egg = '🍳', cheese = '🐮']) {
egg; // '🍳'
cheese; // '🐮'
}
omelette(); // 👈 NOT passing any value
解构剩余参数
@lukeshiru:你也可以这样做。
function omelette(...[egg, cheese]) {
egg; // '🥚'
cheese; // '🧀'
}
omelette('🥚', '🧀');
☝️ 我来分析一下@lukeshiru在这里做的事情,因为乍一看可能有点奇怪。其实这和下面这个是一样的:
// Step 1: using the rest parameter to collect the arguments
function omelette(...args) {
args; // ['🥚', '🧀']
// Step 2: extract the value using destructuring
const [egg, cheese] = args;
}
我分两步完成了上述操作,但我也可以将所有步骤合并为一步:
// "..." --> reflects the rest parameter
// "[egg, cheese]" --> reflects the destructuring
function omelette(...[egg, cheese]) {
egg; // '🥚'
cheese; // '🧀'
}
资源
- MDN Web 文档:数组解构
- ES6:解构——从 JavaScript 中的数组和对象中提取数据
- GitHub Gist:解构
- ES6 中的解构赋值
- MDN Web 文档:参数对象
- Stack Overflow:参数和形参之间有什么区别?
- Stack Overflow:参数
- 最初发表于 www.samanthaming.com
感谢阅读❤
打个招呼!Instagram | Twitter | SamanthaMing.com