默认参数(Default Parameters)
概述
ES6 允许在函数参数中设置默认值,当调用函数时没有提供该参数或参数值为 undefined 时,使用默认值。
基本语法
传统方式
// 传统方式:在函数体内设置默认值
function greet(name) {
name = name || 'Guest';
return `Hello, ${name}!`;
}
// 问题:当传入假值(0, '', false, null)时也会使用默认值
greet(0); // "Hello, Guest!"(错误)
greet(''); // "Hello, Guest!"(错误)
ES6 默认参数
function greet(name = 'Guest') {
return `Hello, ${name}!`;
}
greet(); // "Hello, Guest!"
greet('John'); // "Hello, John!"
greet(undefined); // "Hello, Guest!"
greet(null); // "Hello, null!"(null 不会触发默认值)
greet(0); // "Hello, 0!"
greet(''); // "Hello, !"
参数默认值的触发条件
默认参数只在参数为 undefined 时触发:
function test(value = 'default') {
console.log(value);
}
test(); // "default"(未传参)
test(undefined); // "default"(显式传入 undefined)
test(null); // null
test(0); // 0
test(false); // false
test(''); // ""(空字符串)
多个默认参数
function createUser(
name = 'Anonymous',
age = 0,
email = 'no-email@example.com'
) {
return { name, age, email };
}
createUser();
// { name: 'Anonymous', age: 0, email: 'no-email@example.com' }
createUser('John', 25);
// { name: 'John', age: 25, email: 'no-email@example.com' }
createUser('Jane', 30, 'jane@example.com');
// { name: 'Jane', age: 30, email: 'jane@example.com' }
默认参数的计算
默认参数可以是表达式或函数调用:
// 表达式
function multiply(a, b = a * 2) {
return a * b;
}
multiply(5); // 50 (5 * 10)
multiply(5, 3); // 15 (5 * 3)
// 函数调用
function getDefaultName() {
return 'Guest';
}
function greet(name = getDefaultName()) {
return `Hello, ${name}!`;
}
greet(); // "Hello, Guest!"
默认参数与解构
对象解构中的默认值
function createUser({ name = 'Anonymous', age = 0 } = {}) {
return { name, age };
}
createUser(); // { name: 'Anonymous', age: 0 }
createUser({ name: 'John' }); // { name: 'John', age: 0 }
createUser({ age: 25 }); // { name: 'Anonymous', age: 25 }
数组解构中的默认值
function processCoords([x = 0, y = 0] = []) {
return { x, y };
}
processCoords(); // { x: 0, y: 0 }
processCoords([10]); // { x: 10, y: 0 }
processCoords([10, 20]); // { x: 10, y: 20 }
默认参数的作用域
默认参数有自己的作用域,位于函数体作用域之前:
let x = 1;
function foo(x = x) {
console.log(x);
}
foo(); // ReferenceError: x is not defined
// 默认参数 x = x 中,x 指向的是参数作用域中的 x,而不是外部的 x
let x = 1;
function foo(a = x) {
console.log(a);
}
foo(); // 1(正常工作)
默认参数的暂时性死区
function foo(a = b, b = 1) {
console.log(a, b);
}
foo(); // ReferenceError: b is not defined
// 参数 a 的默认值 b 在此时还未定义
实际应用示例
1. 配置对象处理
function createServer({
port = 3000,
host = 'localhost',
ssl = false,
timeout = 5000,
maxConnections = 100
} = {}) {
console.log(`Server: ${host}:${port}`);
console.log(`SSL: ${ssl}, Timeout: ${timeout}ms`);
console.log(`Max connections: ${maxConnections}`);
}
createServer(); // 使用所有默认值
createServer({ port: 8080, ssl: true }); // 只覆盖部分配置
2. API 请求函数
async function fetchUsers({
page = 1,
limit = 10,
sortBy = 'createdAt',
order = 'desc'
} = {}) {
const params = new URLSearchParams({ page, limit, sortBy, order });
const response = await fetch(`/api/users?${params}`);
return response.json();
}
// 使用示例
fetchUsers(); // 默认参数
fetchUsers({ page: 2, limit: 20 }); // 自定义参数
3. 事件处理函数
function handleEvent(
event,
callback = () => {},
options = {}
) {
const {
preventDefault = true,
stopPropagation = false
} = options;
if (preventDefault) {
event.preventDefault();
}
if (stopPropagation) {
event.stopPropagation();
}
callback(event);
}
// 使用示例
button.addEventListener('click', (e) => {
handleEvent(e, () => console.log('Clicked'));
});
link.addEventListener('click', (e) => {
handleEvent(e, () => console.log('Link clicked'), {
preventDefault: false
});
});
4. 数据验证函数
function validateUser({
name = '',
email = '',
age = 0,
required = ['name', 'email']
} = {}) {
const errors = [];
required.forEach(field => {
if (!eval(field)) {
errors.push(`${field} is required`);
}
});
if (email && !email.includes('@')) {
errors.push('Invalid email format');
}
if (age < 0 || age > 150) {
errors.push('Invalid age');
}
return { valid: errors.length === 0, errors };
}
注意事项
1. 参数顺序
默认参数应该放在非默认参数之后:
// 不推荐
function bad(a = 1, b) {
return a + b;
}
// 推荐
function good(a, b = 1) {
return a + b;
}
2. 性能考虑
默认参数表达式在每次调用时都会求值:
function expensive() {
console.log('Computing...');
return 42;
}
function test(x = expensive()) {
console.log(x);
}
test(); // "Computing..." "42"
test(); // "Computing..." "42"(每次都执行)
3. 与 arguments 对象的关系
function test(a = 1) {
console.log(arguments.length);
console.log(a);
}
test(); // 0, 1
test(10); // 1, 10
test(10, 20); // 2, 10
最佳实践
- 使用默认参数替代传统方式:更清晰、更安全
- 为可选参数设置合理默认值:提高函数的易用性
- 避免副作用:默认参数表达式应该是纯函数
- 文档化参数:清晰说明每个参数的作用和默认值
// 好的做法
/**
* 创建用户对象
* @param {Object} options - 配置选项
* @param {string} options.name - 用户名,默认 'Anonymous'
* @param {number} options.age - 年龄,默认 0
* @returns {Object} 用户对象
*/
function createUser({
name = 'Anonymous',
age = 0
} = {}) {
return { name, age };
}
参考
目录