Исключения в JavaScript, я должен их использовать и как? - PullRequest
5 голосов
/ 26 мая 2011

Мне несколько раз говорили, что это "плохо" - использовать исключения в javascript. На самом деле не сказали, почему это плохо, но вместо этого я должен использовать вместо этого break, continue и return.

Что нормально, кроме того, что мне не нужно возвращаться / прерываться / продолжать, мне нужно бросать. У меня есть случай, когда у меня есть функции итератора, вложенные друг в друга, каждая возвращает следующее значение при вызове, поэтому я использую исключение, чтобы указать, что итерировать больше нечего: кажется логичным способом сделать это, делает код чистым и отлично работает на практике. Есть ли причина не использовать исключения в js?

Второй вопрос, когда я использую исключения, какие объекты я должен бросать? В случае ошибок я, очевидно, выбрасываю экземпляры Error, но в особых случаях (остановка итерации и т. Д.) Мне нужен был быстрый способ проверки этих конкретных исключений, и я просто определил пустую именованную функцию (function StopIteration () }) и так как функции сравниваются по ссылке, я всегда могу проверить, является ли это моим особым случаем, или я должен просто перебросить. Есть ли лучший или более нелепый способ сделать это в JS? Должен ли я действительно попытаться изменить свой код, чтобы избежать использования исключений?

Спасибо

Ответы [ 4 ]

3 голосов
/ 26 мая 2011

Звучит так, как будто вы ищете в многомерном пространстве с использованием вложенных циклов, что довольно распространенная вещь для программирования. Соблазнительно бросить исключение из самого внутреннего цикла, когда цель найдена, которая затем захватывается блоком «catch» вокруг самого внешнего цикла, но это часто считается плохой практикой.

Разработчики языка знают об этой ловушке, поэтому они позволяют нам давать метки (имена) для зацикливания структур, чтобы мы могли от них оторваться (или продолжить к ним). Рассмотрим этот пример:

function findValueInMatrix(value, matrix) {
  var r, c, coords, rows=matrix.length, cols=matrix[0].length;
  found: // Label the outer loop as "found" so we can break from it.
  for (r=0; r<rows; r++) {
    for (c=0; c<cols; c++) {
      if (matrix[r][c] == value) {
        coords = [r, c]
        break found; // Exit the loop labeled "found".
      }
    }
  }
  return coords;
}

Вы можете найти больше информации в этом посте о разрыве от вложенных циклов .

Этот тестовый пример jsPerf также демонстрирует, что разбиение на метку номинально быстрее, чем создание исключения (предположительно в большинстве браузеров).

2 голосов
/ 26 мая 2011
Обработка исключений

обычно медленнее, чем обычная оценка, и только для исключительных ситуаций

для остановки итераций лучше определить функцию hasNext или isEmpty для конечного условия или вернуть значение часового (например, undefined), когда больше нет элементов, поэтому цикл становится

//with hasNext
while(it.hasNext()){
var val = it.next();
//...
}
//or with a sentinal undefined
while( (val = it.next()) !== undefined){
//...
}
0 голосов
/ 06 сентября 2013

Создание исключения, чтобы вырваться из вложенного рекурсивного поиска / обхода - это самый простой и более элегантный путь.

Скажем, вы гуляете по дереву, рекурсивно вызывая функцию для обработки текущего узла , вызывая снова для каждого из его дочерних элементов и так далее.

Когда вы обрабатываете каждый узел , вы можете полностью разбить весь стек вызовов и вернуть найденное значение (или прекратить итерацию в целом), выход из всех циклов, которые ожидают в предыдущих вызовах. Имейте в виду, что эти предыдущие вызовы могут быть дорогостоящими в обработке и памяти, но бесполезны, если вы «нашли» свой результат. Бросить исключение - это самый эффективный и простой способ для достижения этой цели, но, конечно, это требует внимания.

Для простых (даже вложенных) циклов это перебор и справедливо называется анти-паттерном.

0 голосов
/ 26 мая 2011

Для некоторых людей создание исключений, указывающих на то, что значений больше нет, является плохим стилем; исключения сделаны для исключительного поведения .

Более того, обработка исключений обычно выполняется медленнее, чем простые тесты. Разница действительно незначительна (и, возможно, даже не существует), если брошенный экземпляр создается не каждый раз. Таким образом, иметь постоянную StopIteration и бросать ее на самом деле довольно быстро.

Для вашей проблемы вы можете увидеть https://developer.mozilla.org/en/JavaScript/Guide/Iterators_and_Generators (они используют исключения для остановки итерации). Я обнаружил, что в динамически типизированных языках исключения используются и для такого рода целей.

...