ES5以及之前的参数默认值
缺点:
1. 写起来很麻烦,并且代码的阅读性是比较差的
2. 这种写法有bug
如果你输入的值被隐式的转化为false,foo函数中会使用默认参数,我们可能就想使用那些隐式转换的值,就造成了麻烦
function foo(m, n) {
m = m || 'aaa'
n = n || 'bbb'
console.log(m, n)
}
//'', 0, NaN, null, undefined
foo('', 'a')
foo(0, 1)
foo(NaN, 'why')
foo(null, 'why')
foo(undefined, 'why')
ES6 的默认值
function foo(m = 'aaa', n = 'bbb'){
console.log(m, n)
}
foo('', 'a')
foo(0, 1)
foo(NaN, 'why')
foo(null, 'why')
foo(undefined, 'why')
可以看到除了值为undefined的使用了默认值,其他的都使用了自身的值。第一个为空的字符串,不代表不存在
默认值也可以是表达式或函数
function getDefaultName() {
return "Anonymous";
}
function showName(name = getDefaultName()) {
console.log(`Name: ${name}`);
}
showName(); // Name: Anonymous
showName('why') //Name: why
配合解构使用
function printInfo1({name, age} = {name: 'why', age: 18}){
console.log(name,age)
}
printInfo1({name: 'kobe', age: 40}) //kobe 40
function printInfo2({name = 'why', age = 18} = {}){
console.log(name,age)
}
printInfo2()//why 18
| 函数 | 默认值加在哪里? | 解构内有默认值? |
|---|---|---|
printInfo1 | 整个参数对象默认值 | ❌ |
printInfo2 | 参数是空对象的默认值 {} | ✅ 每个属性有默认值 |
| 场景 | printInfo1 | printInfo2 |
|---|---|---|
| 默认值位置 | 整个对象参数的默认值 | 解构属性各自有默认值 |
| 能否省略传参? | ✅ 可以(如果函数写了整体默认值) | ✅ 可以(参数为 undefined 会变成 {}) |
| 适合什么场景? | 有完整对象时给整个默认 | 参数可能是部分字段、不传字段时更灵活 |
函数默认值对函数的length属性的影响
function foo(x, y, z, m) {
console.log(x, y, z, m);
}
console.log(foo.length) //4
function foo(x, y, z = 1, m) {
console.log(x, y, z, m);
}
console.log(foo.length) //2
函数中length属性,对默认参数,以及默认参数后面的参数一律都不计算在内。
如果函数第一个参数为默认值参数,则length为0
剩余参数
一、arguments 是什么?
- 是函数内部的一个类数组对象
- 包含了传入函数的所有参数
- 在普通函数中默认存在
- 不能在箭头函数中使用!
function demo1(a, b) {
console.log(arguments); // [Arguments] { '0': 1, '1': 2, '2': 3 }
}
demo1(1, 2, 3);
🟢 二、rest parameter 是什么?
- 是 ES6 引入的新语法
- 用语法
...args来表示剩余参数(是一个真正的数组) - 只能放在参数列表的最后一个位置
function demo2(...args) {
console.log(args); // [1, 2, 3]
}
demo2(1, 2, 3);
三、两者区别总结表
| 特性 | arguments | rest parameter (...args) |
|---|---|---|
| 是否为数组 | ❌ 类数组对象 | ✅ 真正的数组 |
| 支持哪些函数 | ✅ 普通函数(function) | ✅ 普通函数 & 箭头函数 |
| 使用方式是否明确 | ❌ 拿所有参数,无名字 | ✅ 有名字,且更灵活 |
| 是否推荐 | ❌ 不推荐(已过时) | ✅ 推荐(现代写法) |
举个完整对比的例子:
function showArgs1(a, b) {
console.log(arguments[0]); // 1
console.log(arguments.length); // 3
}
showArgs1(1, 2, 3);
function showArgs2(...args) {
console.log(args[0]); // 1
console.log(args.length); // 3
}
showArgs2(1, 2, 3);
arguments 不适用于箭头函数
const demo = () => {
console.log(arguments); // ❌ 报错 ReferenceError: arguments is not defined
}
最佳实践(现代 JS 推荐用法)
function sum(...nums) {
return nums.reduce((a, b) => a + b, 0);
}
console.log(sum(1, 2, 3, 4)); // 输出 10
拓展:rest 参数配合解构
const [first, ...rest] = [1, 2, 3, 4];
console.log(first); // 1
console.log(rest); // [2, 3, 4]
arguments是旧时代的产物,功能强但不方便;而rest parameter是更现代、更灵活、更强大的写法,推荐你优先使用 rest 参数。而出现rest参数就是希望替代arguments的
箭头函数
| 特性 | 描述 |
|---|---|
| ✅ 更简洁的写法 | 少了 function 和 return |
✅ 自动绑定 this | 不会改变 this 指向(继承外层作用域) |
❌ 没有 arguments | 要用 rest 参数 ...args 替代 |
| ❌ 不能用作构造函数 | 箭头函数不能用 new 调用 |
❌ 没有 super 和 new.target | 在类中也不能用箭头函数作为方法 |
补充:箭头函数的this和arguments属性自身没有,会去上层作用域找