共计 3718 个字符,预计需要花费 10 分钟才能阅读完成。
作者:Dmitri Pavlutin
译者:前端小智
来源:dmitripavlutin
为了保证的可读性,本文采用意译而非直译。
想阅读更多优质文章请猛戳 GitHub 博客, 一年百来篇优质文章等着你!
顺便说件事,这几天送给读者福利,周三开奖没有抽奖可以看看,没有套路:https://mp.weixin.qq.com/s/mbPrvhheFJ6mSFcaoki3IQ
函数是一段结合在一起执行特定任务的代码,函数一般使用参数与外部进行交互。要编写简洁高效的 JS 代码,必须掌握函数参数。
在本文中,会使用一些有趣的例子来解释 JS 必须有效地处理函数参数的所有特性。
1. 函数参数
JS 函数可以有任意数量的参数。咱们来定义具有 0
、1
和2
个参数的函数。
// 0 个参数
function zero() {return 0;}
// 1 个参数
function identity(param) {return param;}
// 2 个参数
function sum(param1, param2) {return param1 + param2;}
zero(); // => 0
identity(1); // => 1
sum(1, 2); // => 3
上面的 3
个函数调用传入的参数个数与函数定义参数个数相同。当然传入参数比定义参数个数少的时候,JS 允许咱们这样,不会报错,缺少会使用 undefined
代替。
例如,咱们用一个参数调用函数sum()
(它有两个参数)
function sum(param1, param2) {console.log(param1); // 1
console.log(param2); // undefined
return param1 + param2;
}
sum(1); // => NaN
只有一个参数调用该函数:sum(1)
。这样 param1
的值是 1
,但是第二个参数param2
是会用 undefined
初始化的。
param1 + param2
的值为1 + undefined
,结果为NaN
。
如果有必要,可以验证参数是否是 undefined
,并提供一个默认值。
function sum(param1, param2) {if (param2 === undefined) {param2 = 0;}
return param1 + param2;
}
sum(1); // => 1
当然还有更好做法,就是使用默认参数,来看看。
2. 默认参数
ES6 默认参数特性允许使用默认值初始化参数。这种比上面介绍的方法更好、更简洁。
接着使用 ES6 默认参数特性将 param2
默认为0
。
function sum(param1, param2 = 0) {console.log(param2); // => 0
return param1 + param2;
}
sum(1); // => 1
sum(1, undefined); // => 1
现在如果没有传入第二个参数,param2
就默认为 0。
注意 ,如果将undefined
设置为第二个参数 sum(1, undefined)
,param2
也将初始化为0
。
3. 解构参数
在 JS 函数参数中,咱特别喜欢的是解构的特性。可以将内联参数的对象或数组进行解构。这个特性使得从参数对象中提取一些属性非常有用
function greet({name}) {return `Hello, ${name}!`;
}
const person = {name: '前端小智'};
greet(person); // => 'Hello, 前端小智!'
{name}
是应用于对象解构的参数。
当然也可以结合 默认参数:
function greetWithDefault({name = '无名氏'} = {}) {return `Hello, ${name}!`;
}
greetWithDefault(); // => 'Hello, 无名氏!'
{name = 'Unknown'} ={}
默认为空对象。
可以使用组合不同类型解构的所有功能。例如,让我们对同一个参数使用对象和数组解构。
function greeFirstPerson([{name}]) {return `Hello, ${name}!`;
}
const persons = [{name: '王小智'}, {name: '王大治'}];
greeFirstPerson(persons); // => 'Hello, 王小智!'
[{name}]
的解构较为复杂,它提取数组的第一项,然后从中对象读取 name
属性。
4. arguments 对象
JS 函数的另一个很好的特性是能够用可变参数调用同一个函数。这样可以使用 arguments
对象来获取传入的所有参数。
arguments
对象是所有(非箭头)函数中都可用的局部变量。你可以使用 arguments
对象在函数中引用函数的参数。
例如,对函数的参数求和:
function sumArgs() {console.log(arguments); // {0: 5, 1: 6, length: 2}
let sum = 0;
for (let i = 0; i < arguments.length; i++) {sum += arguments[i];
}
return sum;
}
sumArgs(5, 6); // => 11
arguments 是一个对应于传递给函数的参数的类数组对象。
有个问题是,每个函数作用域都定义了自己的 arguments
对象。因此,可能需要一个额外的变量来访问外部函数作用域arguments
:
function outerFunction() {
const outerArguments = arguments;
return function innerFunction() {
// outFunction arguments
outerArguments[0];
};
}
4.1 箭头函数情况
有一种特殊情况: 箭头 w 函数中没有arguments
。
const sumArgs = () => {console.log(arguments);
return 0;
};
// throws: "Uncaught ReferenceError: arguments is not defined"
sumArgs();
但这问题不。可以使剩余参数访问箭头函数内的所有参数。来 look look。
5. 剩余参数
剩余参数 语法允许咱们将一个不定数量的参数表示为一个 数组。
老样子,来 see see。
function sumArgs(...numbers) {console.log(numbers); // [5, 6]
return numbers.reduce((sum, number) => sum + number);
}
sumArgs(5, 6); // => 11
...numbers
是一个 剩余参数,它将成为一个由剩余参数组成的真数组[5,6]
。由于numbers
是一个数组,所以就可以使用数组自有方法reduce
(与类数组对象的参数相反)。
如果不想在剩余参数中收集所有参数,则可以组合 常规参数 和剩余参数。
function multiplyAndSumArgs(multiplier, ...numbers) {console.log(multiplier); // 2
console.log(numbers); // [5, 6]
const sumArgs = numbers.reduce((sum, number) => sum + number);
return multiplier * sumArgs;
}
multiplyAndSumArgs(2, 5, 6); // => 22
multiplier
是一个常规参数,它获取第一个参数的值。然后剩下的参数...numbers
接收剩余的参数。
剩余参数和 arguments 对象的区别
剩余参数和 arguments 对象之间的区别主要有三个:
- 剩余参数只包含那些没有对应形参的实参,而 arguments 对象包含了传给函数的所有实参。
-
arguments
对象不是一个真正的数组,而剩余参数是真正的Array
实例,也就是说你能够在它上面直接使用所有的数组方法,比如sort
,map
,forEach
或pop
。 -
arguments
对象还有一些附加的属性(如callee
属性)。
6. 总结
除了基本用法之外,JS 在处理函数参数时还提供了许多有用的特性。
当缺少参数时,可以很容易地设置默认值。
JS 解构的所有功能都可以应用于参数。甚至可以将解构与默认参数结合使用。
arguments
是一个特殊的类数组对象,它包含函数调用时使用的所有参数。
作为 arguments
的更好替代,可以使用剩余参数特性。它也保存参数列表,但是,它将它们存储到数组中。
代码部署后可能存在的 BUG 没法实时知道,事后为了解决这些 BUG,花了大量的时间进行 log 调试,这边顺便给大家推荐一个好用的 BUG 监控工具 Fundebug。
原文:https://dmitripavlutin.com/ja…
交流
阿里云最近在做活动,低至 2 折,有兴趣可以看看:https://promotion.aliyun.com/…
干货系列文章汇总如下,觉得不错点个 Star,欢迎 加群 互相学习。
https://github.com/qq44924588…
我是小智,公众号「大迁世界」作者,对前端技术保持学习爱好者。我会经常分享自己所学所看的干货,在进阶的路上,共勉!
关注公众号,后台回复 福利,即可看到福利,你懂的。