剩余参数 ...args 的灵活运用

ES6 (ECMAScript 2015) 引入了许多强大的新特性,其中剩余参数(Rest Parameters)是一个极其有用的语法糖,它使用 ... 前缀表示,可以让我们以更优雅的方式处理函数参数。

剩余参数的基本概念

剩余参数语法允许我们将不定数量的参数表示为一个数组:

javascript 复制代码
function sum(...numbers) {
  return numbers.reduce((acc, curr) => acc + curr, 0);
}

console.log(sum(1, 2, 3, 4)); // 输出: 10

与传统的 arguments 对象相比,剩余参数是真正的数组,可以直接使用数组方法。

剩余参数的灵活应用

1. 与常规参数结合使用

剩余参数不一定要放在所有参数的最后,但必须是最后一个形参:

javascript 复制代码
function joinStrings(separator, ...strings) {
  return strings.join(separator);
}

console.log(joinStrings('-', 'hello', 'world')); // 输出: "hello-world"

2. 解构剩余参数

我们可以对剩余参数进行解构:

javascript 复制代码
function processUser([first, ...rest], ...otherInfo) {
  console.log(`First name: ${first}`);
  console.log(`Other names: ${rest.join(' ')}`);
  console.log(`Additional info: ${otherInfo}`);
}

processUser(['John', 'Doe', 'Smith'], 'age:30', 'city:NY');

3. 在箭头函数中使用

箭头函数没有自己的 arguments 对象,剩余参数是获取所有参数的理想方式:

javascript 复制代码
const multiply = (...nums) => nums.reduce((acc, num) => acc * num, 1);
console.log(multiply(2, 3, 4)); // 输出: 24

4. 类型检查和默认值

可以结合类型检查和默认值使用剩余参数:

javascript 复制代码
function addOnlyNumbers(...args) {
  return args.filter(arg => typeof arg === 'number')
             .reduce((sum, num) => sum + num, 0);
}

console.log(addOnlyNumbers(1, '2', 3)); // 输出: 4 (忽略字符串)

实际应用场景

1. 创建灵活的API

javascript 复制代码
function createElement(tag, attributes = {}, ...children) {
  const element = document.createElement(tag);
  
  // 设置属性
  Object.entries(attributes).forEach(([key, value]) => {
    element.setAttribute(key, value);
  });
  
  // 添加子元素
  children.forEach(child => {
    if (typeof child === 'string') {
      element.appendChild(document.createTextNode(child));
    } else {
      element.appendChild(child);
    }
  });
  
  return element;
}

const el = createElement('div', { class: 'container' }, 
  createElement('p', {}, 'Hello'),
  ' World!'
);

2. 函数组合

javascript 复制代码
function compose(...fns) {
  return fns.reduce((f, g) => (...args) => f(g(...args)));
}

const add5 = x => x + 5;
const multiply3 = x => x * 3;
const square = x => x * x;

const transform = compose(square, multiply3, add5);
console.log(transform(2)); // ((2 + 5) * 3)^2 = 441

3. 日志记录器

javascript 复制代码
function createLogger(prefix) {
  return function(...messages) {
    console.log(`[${prefix}]`, ...messages);
  };
}

const infoLogger = createLogger('INFO');
const errorLogger = createLogger('ERROR');

infoLogger('Application started', new Date());
errorLogger('Something went wrong!', { code: 500 });

注意事项

  1. 一个函数只能有一个剩余参数
  2. 剩余参数必须是最后一个参数
  3. 剩余参数不计入函数的 length 属性
  4. 箭头函数没有 arguments 对象,剩余参数是更好的选择

剩余参数 ...args 是 ES6 中一个简单但强大的特性,它极大地提高了 JavaScript 函数参数处理的灵活性和表达能力。通过合理运用,可以使代码更加简洁、可读性更强,同时保持高度的灵活性。