Книга: JavaScript. Подробное руководство, 6-е издание

8.3.4. Типы аргументов

8.3.4. Типы аргументов

В языке JavaScript параметры функций объявляются без указания их типов, а во время передачи значений функциям не производится никакой проверки их типов. Вы можете сделать свой программный код самодокументируемым, выбирая описательные имена для параметров функций и включая описание типов аргументов в комментарии, как это сделано в только что рассмотренном примере функции аггаусору(). Для необязательных аргументов в комментарий можно добавлять слово «необязательный» («optional»). А если функция может принимать произвольное число аргументов, можно использовать многоточие:

function max(/* число... */) { /* тело функции */ }

Как отмечалось в разделе 3.8, при необходимости JavaScript выполняет преобразование типов. Таким образом, если определить функцию, которая ожидает получить строковый аргумент, а затем вызвать ее с аргументом какого-нибудь другого типа, значение аргумента просто будет преобразовано в строку, когда функция пытается обратиться к нему как к строке. В строку может быть преобразовано любое простое значение, и все объекты имеют методы toString() (правда, не всегда полезные); тем самым устраняется вероятность появления ошибки.

Однако такой подход может использоваться не всегда. Вернемся к методу аггаусору(), продемонстрированному выше. Он ожидает получить массив в первом аргументе. Любое обращение к функции окажется неудачным, если первым аргументом будет не массив (или, возможно, объект, подобный массиву). Если функция должна вызываться чаще, чем один-два раза, следует добавить в нее проверку соответствия типов аргументов. Гораздо лучше сразу же прервать вызов функции в случае передачи аргументов ошибочных типов, чем продолжать выполнение, которое потерпит неудачу с сообщением об ошибке, запутывающим ситуацию. Ниже приводится пример функции, выполняющей проверку типов. Обратите внимание, что она использует функцию isArrayLike() из раздела 7.11:

// Возвращает сумму элементов массива (или объекта, подобного массиву) а.
// Все элементы массива должны быть числовыми, при этом значения null
// и undefined игнорируются,
function sum(a) {
  if (isArrayLike(a)) {
    var total = 0;
    for(var і = 0; і < a.length; і++) { // Цикл по всем элементам
      var element = a[і];
      if (element == null) continue; // Пропустить null и undefined
      if (isFinite(element))
        total += element;
      else throw new Error("sum(): все элементы должны быть числами");
    }
    return total;
  }
  else throw new Error("sum(): аргумент должен быть массивом");
}

Этот метод sum() весьма строго относится к проверке типов входных аргументов и генерирует исключения с достаточно информативными сообщениями, если типы входных аргументов не соответствуют ожидаемым. Тем не менее он остается достаточно гибким, обслуживая наряду с настоящими массивами объекты, подобные массивам, и игнорируя элементы, имеющие значения null и undefined.

JavaScript - чрезвычайно гибкий и к тому же слабо типизированный язык, благодаря чему можно писать функции, которые достаточно терпимо относятся к количеству и типам входных аргументов. Далее приводится метод flexsum(), реализующий такой подход (и, вероятно, являющийся примером другой крайности). Например, он принимает любое число входных аргументов и рекурсивно обрабатывает те из них, которые являются массивами. Вследствие этого он может принимать переменное число аргументов или массив аргументов. Кроме того, он прилагает максимум усилий, чтобы преобразовать нечисловые аргументы в числа, прежде чем сгенерировать исключение:

function flexisum(a) { var total = 0;
  for(var і = 0; і < arguments.length; i++) {
    var element = arguments[i], n;
    if (element == null) continue; // Игнорировать null и undefined
    if (isArray(element)) // Если аргумент - массив
      n = flexisum.apply(this. element); // вычислить сумму рекурсивно
    else
      if (typeof element === "function") // Иначе, если это функция...
        n = Number(element()); // вызвать и преобразовать,
      else
        n = Number(element); // Иначе попробовать преобразовать
    if (isNaN(n)) // Если не удалось преобразовать в число, возбудить искл.
      throw Error("flexisum(): невозможно преобразовать " + element + в число");
    total += n; // Иначе прибавить n к total
  }
  return total;
}

Оглавление книги


Генерация: 0.798. Запросов К БД/Cache: 3 / 0
поделиться
Вверх Вниз