阿里云主机折上折
  • 微信号
Current Site:Index > The rest parameter syntax

The rest parameter syntax

Author:Chuan Chen 阅读数:59959人阅读 分类: JavaScript

Basic Concepts of Rest Parameters

The rest parameter syntax introduced in ECMAScript 6 allows us to represent an indefinite number of arguments as an array. This syntax is implemented by adding three dots (...) before a function parameter, solving the cumbersome issue of using the arguments object to handle variable arguments in ES5.

function sum(...numbers) {
  return numbers.reduce((prev, curr) => prev + curr, 0);
}

console.log(sum(1, 2, 3)); // Outputs 6
console.log(sum(1, 2, 3, 4, 5)); // Outputs 15

Differences Between Rest Parameters and the arguments Object

Rest parameters differ from the traditional arguments object in several key ways:

  1. Rest parameters are true array instances and can directly use array methods.
  2. The arguments object contains all arguments, while rest parameters only include the remaining arguments that don't have corresponding formal parameters.
  3. Rest parameters must be the last in the parameter list.
// Using the `arguments` object
function oldWay() {
  const args = Array.prototype.slice.call(arguments);
  return args.join('-');
}

// Using rest parameters
function newWay(...args) {
  return args.join('-');
}

console.log(oldWay('a', 'b', 'c')); // "a-b-c"
console.log(newWay('a', 'b', 'c')); // "a-b-c"

Typical Use Cases for Rest Parameters

Collecting Function Arguments

The most common use of rest parameters is to collect excess function arguments:

function logWithPrefix(prefix, ...messages) {
  messages.forEach(message => {
    console.log(`${prefix}: ${message}`);
  });
}

logWithPrefix('INFO', 'System started', 'Configuration loaded', 'Service ready');

Replacing the apply Method

In ES5, we needed to use apply to spread an array into arguments. Now, we can use rest parameters and the spread operator:

// ES5 way
Math.max.apply(null, [1, 2, 3]);

// ES6 way
Math.max(...[1, 2, 3]);

// Combining with rest parameters
function wrapper(...args) {
  return Math.max(...args);
}

Rest Parameters in Destructuring Assignment

Rest parameter syntax can also be used in destructuring assignments:

const [first, second, ...rest] = [1, 2, 3, 4, 5];
console.log(first); // 1
console.log(second); // 2
console.log(rest); // [3, 4, 5]

const {a, b, ...others} = {a: 1, b: 2, c: 3, d: 4};
console.log(a); // 1
console.log(b); // 2
console.log(others); // {c: 3, d: 4}

Notes on Rest Parameters

  1. Rest parameters must be the last parameter in a function:
// Incorrect example
function invalid(a, ...b, c) {
  // SyntaxError: Rest parameter must be last formal parameter
}
  1. Rest parameters are not counted in a function's length property:
function func1(a, b) {}
function func2(a, b, ...c) {}

console.log(func1.length); // 2
console.log(func2.length); // 2
  1. Arrow functions can also use rest parameters:
const sum = (...nums) => nums.reduce((a, b) => a + b, 0);

Advanced Uses of Rest Parameters

Type Checking and Argument Validation

Rest parameters can be used for argument type checking:

function checkTypes(...args) {
  const types = args.map(arg => typeof arg);
  console.log('Argument types:', types);
}

checkTypes(1, 'text', true, {}, []); 
// Output: ["number", "string", "boolean", "object", "object"]

Implementing Function Composition

Rest parameters make it easy to implement function composition:

function compose(...fns) {
  return x => fns.reduceRight((v, f) => f(v), x);
}

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

Creating Variadic Constructors

Using rest parameters in classes:

class Point {
  constructor(...coords) {
    this.coords = coords;
  }
  
  get dimensions() {
    return this.coords.length;
  }
}

const point2D = new Point(10, 20);
const point3D = new Point(10, 20, 30);

console.log(point2D.dimensions); // 2
console.log(point3D.dimensions); // 3

Differences Between Rest Parameters and the Spread Operator

Although both rest parameters and the spread operator use the three-dot (...) syntax, they serve opposite purposes:

  • Rest parameters collect multiple arguments into an array.
  • The spread operator expands an array or object into multiple elements.
// Rest parameters: collecting
function collect(...items) {
  console.log(items);
}

// Spread operator: expanding
const numbers = [1, 2, 3];
console.log(...numbers); // Equivalent to console.log(1, 2, 3)

Practical Application Examples

Implementing a Simple Logger

class Logger {
  constructor(prefix = 'LOG') {
    this.prefix = prefix;
  }
  
  log(...messages) {
    const timestamp = new Date().toISOString();
    console.log(`[${timestamp}] ${this.prefix}:`, ...messages);
  }
}

const appLogger = new Logger('APP');
appLogger.log('User logged in', {username: 'admin'});
appLogger.log('Data loaded', 'Time taken: 200ms');

Creating a Flexible API Request Function

async function apiRequest(method, endpoint, ...params) {
  let options = {};
  
  if (method === 'GET') {
    endpoint += '?' + new URLSearchParams(params[0]).toString();
  } else {
    options = {
      method,
      headers: {'Content-Type': 'application/json'},
      body: JSON.stringify(params[0] || {})
    };
  }
  
  const response = await fetch(endpoint, options);
  return response.json();
}

// Usage examples
apiRequest('GET', '/api/users', {page: 1, limit: 10})
  .then(data => console.log(data));

apiRequest('POST', '/api/users', {name: 'John', age: 30})
  .then(data => console.log(data));

Performance Considerations

While rest parameters offer convenience, there are performance considerations in sensitive scenarios:

  1. Each function call creates a new array instance.
  2. For high-frequency function calls, alternative implementations may be necessary.
  3. In most application scenarios, this performance overhead is negligible.
// Performance test example
function testPerformance(fn, iterations = 1000000) {
  const start = performance.now();
  for (let i = 0; i < iterations; i++) {
    fn(1, 2, 3, 4, 5);
  }
  return performance.now() - start;
}

function withRest(...args) {
  return args.length;
}

function withoutRest(a, b, c, d, e) {
  return arguments.length;
}

console.log('With rest parameters:', testPerformance(withRest), 'ms');
console.log('Without rest parameters:', testPerformance(withoutRest), 'ms');

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

Front End Chuan

Front End Chuan, Chen Chuan's Code Teahouse 🍵, specializing in exorcising all kinds of stubborn bugs 💻. Daily serving baldness-warning-level development insights 🛠️, with a bonus of one-liners that'll make you laugh for ten years 🐟. Occasionally drops pixel-perfect romance brewed in a coffee cup ☕.