Обработка параметров в JavaScript

Node.js внешний интерфейс JavaScript

Во-первых, мы знаем, что в js нет перегрузки функций, и когда мы имеем дело с параметрами переменных функций, нам нужно использовать некоторые хитрости.

arguments

arguments — это внутренняя переменная, которая существует в функциях (кроме стрелочных функций). arguments содержит информацию об аргументах, переданных функции. К первому параметру функции можно получить доступ через arguments[0], ко второй функции функции можно получить доступ через arguments[1] и так далее. Тем не менее, arguments не является объектом массива, он доступен только по индексу и имеет свойство длины. Мы можем превратить аргументы в настоящий массив:

var args = Array.prototype.slice.call(arguments);
var args = [].slice.call(arguments);
var args = Array.from(arguments);
var args = [...arguments];

Будут проблемы оптимизации двигателя в аргументах. В последующих эксплуатации навыки мы не будем использовать объект аргументов, но вместо этого использую синтаксис ES6.

неопределенный параметр

определить функциюfunction func([params][,...args]). Указывает, что функция может принимать параметры переменной длины.

function func(...args) {
  // 解构赋值
  console.log(`arguments: ${args}`); // args 是数组
  let [params1, params2, ...paramsRest] = args; // 拿到传入第一个参数 params1 和第二个参数 params2 和剩余参数的数组 paramsRest
}

Теперь давайте реализуем функцию, которая внутренне вызывает другую функцию.

const foo = (params1, params2, params3) => {
  return params1 + params2 + params3;
};

// 我们不需要知道 foo 的形参列表。使用解构操作任意的形参列表。
const func = (...args) => {
  foo(...args); // 函数调用时候展开
  foo.call(null, ...args); // 使用 call 改变 this 的值。
  foo.apply(null, args); // apply 可以直接接收参数数组
};

Точно так же некоторые параметры определяются, а некоторые параметры являются переменными:

function func(params1, ...args) {
  console.log(`arguments: ${args}`); // 剩余参数的数组
}

По привычке в node.js callback обычно используется последним параметром, если промежуточный параметр неопределён, то его нужно судить по typeof:

// 判断参数
function func(err, params1, params2, callback) {
  if (typeof params1 === 'function') {
    callback = params1;
    params1 = null;
    params2 = null;
  } else if (typeof params2 === 'function') {
    callback = params2;
    params1 = null;
  } else if (typeof callback !== 'function') {
    throw new Error('参数错误');
  }
}

// 一些小伎俩
function func(err, ...args) {
  // 回调函数是数组 args 的最后一项
  const callback = typeof args[args.length - 1] === 'function' ? args.pop() : null;
  const [params1 = null, params2 = null] = args;
}

В нативном js некоторые функции могут одновременно получать списки параметров или массивы параметров в качестве параметров, например, concat. Мы также можем воспользоваться этой возможностью concat для написания таких функций:

const func = (...args) => {
  const params = [].concat(...args); // 利用 concat 能同时接受多个参数或单个数组的特性
  console.log(params);
};

параметры по умолчанию

самый простой синтаксис

function func(a, b = 0) {
  return a + b;
}
func(5); // b 默认为 0

В сочетании с деконструкцией и развитием объекта

function func(a, { opt1 = '1', opt2 = '2' }) {
  console.log(a, opt1, opt2);
}
func(0, { opt1: '4' }); // 0 "4" "2"
func(0); // 错误! 因为第二参数没定义

function func1(a, { opt1 = '1', opt2 = '2' } = {}) {
  console.log(a, opt1, opt2);
}
func1(0); // 可以正确运行 0 "1" "2"

Его также можно обработать внутри функции

function func(a, opts) {
  opts = Object.assign(
    {
      opt1: '1',
    },
    opts
  ); // 使用 Object.assign 赋予默认值

  opts = {
    opt1: '1',
    ...opts,
  }; // 和 Object.assign 类似

  const { opts1 = '1', opts2 = '2' } = opts; // 解构赋值,给予默认值。
}

обработка ошибок

В сочетании с синтаксисом параметров по умолчанию мы можем реализовать обнаружение некоторых ошибок, например, требование передачи параметров:

function mandatory() {
  throw new Error('Missing parameter');
}
function foo(mustBeProvided = mandatory()) {
  return mustBeProvided;
}

foo(); // Error: Missing parameter

Проверить максимальную длину параметра

function func(x, y, ...extra) {
  if (extra.length > 0) {
    throw new Error();
  }
}