mozilla
Your Search Results

    Порядок выполнения и обработка ошибок

    This article is in need of an editorial review.

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

    Более подробная информация об инструкциях, рассмотренных в данной главе, содержится в справочнике по JavaScript. Точка с запятой ( ; ) используется для разделения инструкций в коде.

    Любое выражение (expression) в JavaScript является также инструкцией (statement). Чтобы получить более подробную информацию о выражениях, прочитайте Выражения и операторы.

    Инструкция block

    Инструкция block является фундаментальной и используется для группировки других инструкций. Блок ограничивается фигурными скобками:

    { statement_1; statement_2; ... statement_n; }

    Блок обычно используется с управляющими инструкциями (например, if, for, while).

    while (x < 10) { x++; }

    В вышеприведенном примере { x++; } является блоком.

    Обратите внимание на то, что в JavaScript отсутствует область видимости блока до ECMAScript 6. Переменные, объявленные внутри блока, имеют область видимости функции (или скрипта), в которой находится данный блок. Такие переменные доступны за пределами блока. Другими словами, блок не создает новую область видимости. Хотя "автономные" (standalone) блоки являются корректными синтаксическими конструкциями, но вам не следует их использовать, т.к. они не делают то, что вы ожидаете, если вы ожидаете, что они ведут себя как блоки в C или Java. Например:

    var x = 1;
    {
      var x = 2;
    }
    console.log(x); // 2

    В вышеприведенном примере инструкция var x внутри блока находится в той же области видимости, что и инструкция var x перед блоком. В C или Java эквивалентный код выведет значение 1.

    Начиная с ECMAScript 6, оператор let позволяет объявить переменную в области видимости блока. Чтобы получить более подробную информацию, прочитайте let.

    Условные инструкции

    Условная инструкция — это набор команд, которые выполняются, если указанное условие является истинным. JavaScript поддерживает две условные инструкции: if...else и switch.

    Инструкция if...else

    В следующем примере инструкция statement_1 выполняется, если условие condition является истинным, в противном случае выполняется инструкция statement_2. Ветвь else является необязательной.

    if (condition) {
      statement_1;
    } else {
      statement_2;
    }

    Условием может быть любое выражение, которое вычисляется в true или false. Чтобы получить более подробную информацию о значениях true и false, прочитайте Boolean.

    Используйте else if, чтобы последовательно проверить несколько условий:

    if (condition_1) {
      statement_1;
    } else if (condition_2) {
      statement_2;
    } else if (condition_n) {
      statement_n;
    } else {
      statement_else;
    }

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

    if (condition) {
      statement_1_runs_if_condition_is_true;
      statement_2_runs_if_condition_is_true;
    } else {
      statement_3_runs_if_condition_is_false;
      statement_4_runs_if_condition_is_false;
    }

    Нежелательно использовать простые присваивания в условном выражении, т.к. присваивание может быть спутано с равенством при быстром просмотре кода. Например, не используйте следующий код:

    if (x = y) { /* ... */ }
    

    Если вам нужно использовать присваивание в условном выражении, то распространенной практикой является заключение операции присваивания в дополнительные скобки. Например:

    if ( (x = y) ) { /* ... */ }

    Ложные значения

    Следующие значения являются ложными:

    • false
    • undefined
    • null
    • 0
    • NaN
    • пустая строка ( "" )

    Все остальные значения, включая все объекты, будут восприняты как истина при передаче в условное выражение.

    Не путайте примитивные логические значения true и false со значениями true и false объекта Boolean. Например:

    var b = new Boolean(false);
    !!b; // true

    В следующем примере функция checkData возвращает true, если число символов в объекте Text равно трем; в противном случае функция отображает окно alert и возвращает false.

    function checkData() {
      if (document.form1.threeChar.value.length == 3) {
        return true;
      } else {
        alert("Enter exactly three characters. " +
        document.form1.threeChar.value + " is not valid.");
        return false;
      }
    }

    Инструкция switch

    Инструкция switch позволяет сравнить значение выражения с различными вариантами и при совпадении выполнить соответствующий код. Инструкция имеет следующий вид:

    switch (expression) {
       case label_1:
          statements_1
          [break;]
       case label_2:
          statements_2
          [break;]
       ...
       default:
          statements_default
          [break;]
    }
    

    Сначала производится поиск ветви case с меткой label, совпадающей со значением выражения expression. Если совпадение найдено, то соответствующий данной ветви код выполняется до оператора break, который прекращает выполнение switch и передает управление дальше. В противном случае управление передается необязательной ветви default и выполняется соответствующий ей код. Если ветвь default не найдена, то программа продолжит выполняться со строчки, следующей за инструкцией switch. По соглашению ветвь default является последней ветвью, но следовать этому соглашению необязательно.

    Если оператор break отсутствует, то после выполнения кода, который соответствует выбранной ветви, начнется выполнение кода, который следует за ней.

    В следующем примере если fruittype имеет значение "Bananas", то будет выведено сообщение "Bananas are $0.48 a pound." и оператор break прекратит выполнение switch. Если бы оператор break отсутствовал, то был бы также выполнен код, соответствующий ветви "Cherries", т.е. выведено сообщение "Cherries are $3.00 a pound.".

    switch (fruittype) {
      case "Oranges":
        console.log("Oranges are $0.59 a pound.");
        break;
      case "Apples":
        console.log("Apples are $0.32 a pound.");
        break;
      case "Bananas":
        console.log("Bananas are $0.48 a pound.");
        break;
      case "Cherries":
        console.log("Cherries are $3.00 a pound.");
        break;
      case "Mangoes":
        console.log("Mangoes are $0.56 a pound.");
        break;
      case "Papayas":
        console.log("Mangoes and papayas are $2.79 a pound.");
        break;
      default:
       console.log("Sorry, we are out of " + fruittype + ".");
    }
    console.log("Is there anything else you'd like?");

    Инструкции обработки исключений

    Инструкция throw используется, чтобы выбросить исключение, а инструкция try...catch, чтобы его обработать.

    Типы исключений

    Практически любой объект может быть выброшен как исключение. Тем не менее, не все выброшенные объекты создаются равными. Обычно числа или строки выбрасываются как исключения, но часто более эффективным является использование одного из типов исключений, специально созданных для этой цели:

    Инструкция throw

    Используйте инструкцию throw, чтобы выбросить исключение. При выбросе исключения нужно указать выражение, содержащее значение, которое будет выброшено:

    throw expression;

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

    throw "Error2";                                              // string
    throw 42;                                                    // number
    throw true;                                                  // boolean
    throw { toString: function() { return "I'm an object!"; } }; // object
    Примечание: Вы можете выбросить объект как исключение. Вы можете обращаться к свойствам данного объекта в блоке catch.

    В следующем примере объект UserException выбрасывается как исключение:

    function UserException (message) {
      this.message = message;
      this.name = "UserException";
    }
    
    UserException.prototype.toString = function () {
      return this.name + ': "' + this.message + '"';
    }
    
    throw new UserException("Value too high");

    Инструкция try...catch

    Инструкция try...catch состоит из блока try, который содержит одну или несколько инструкций, и нуля или более блоков catch, которые содержат инструкции, определяющие порядок действий при выбросе исключения в блоке try. Иными словами, если в блоке try будет выброшено исключение, то управление будет передано в блок catch. Если в блоке try не возникнет исключений, то блок catch будет пропущен. Блок finally будет выполнен после окончания работы блоков try и catch, вне зависимости от того, было ли выброшено исключение.

    В следующем примере вызывается функция getMonthName, которая возвращает название месяца по его номеру. Если месяца с указанным номером не существует, то функция выбросит исключение "InvalidMonthNo", которое будет перехвачено в блоке catch:

    function getMonthName (mo) {
      mo = mo - 1;
      var months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
      if (months[mo] != undefined) {
        return months[mo];
      } else {
        throw "InvalidMonthNo";
      }
    }
    
    try {
      monthName = getMonthName(myMonth);
    } catch (e) {
      monthName = "unknown";
    }

    Блок catch

    Используйте блок catch, чтобы обработать исключения, сгенерированные в блоке try.

    catch (catchID) { statements }

    JavaScript создает идентификатор catchID, которому присваивается перехваченное исключение, при входе в блок catch; данный идентификатор доступен только в пределах блока catch и уничтожается при выходе из него.

    В следующем примере выбрасывается исключение, которое перехватывается в блоке catch:

    try {
      throw "myException"
    } catch (e) {
      console.error(e);
    }

    Блок finally

    Блок finally содержит код, который будет выполнен после окончания работы блоков try и catch, но до того, как будет выполнен код, который следует за инструкцией try...catch. Блок finally выполняется вне зависимости от того, было ли выброшено исключение. Блок finally выполняется даже в том случае, если исключение не перехватывается в блоке catch.

    В следующем примере открывается файл, затем в блоке try происходит вызов функции writeMyFile, который может выбросить исключение. Если возникает исключение, то оно обрабатывается в блоке catch. В любом случае файл будет закрыт функцией closeMyFile, вызов которой находится в блоке finally.

    openMyFile();
    try {
      writeMyFile(theData);
    } catch(e) {
      handleError(e);
    } finally {
      closeMyFile();
    }

    Если блок finally возвращает значение, то данное значение становится возвращаемым значением всей связки try-catch-finally. Значения, возвращаемые блоками try и catch, будут проигнорированы.

    function f() {
      try {
        console.log(0);
        throw "bogus";
      } catch(e) {
        console.log(1);
        return true;    // приостанавливается до завершения блока `finally`
        console.log(2); // не выполняется
      } finally {
        console.log(3);
        return false;   // заменяет предыдущий `return`
        console.log(4); // не выполняется
      }
      // `return false` выполняется сейчас
      console.log(5);  // не выполняется
    }
    f();               // отображает 0, 1, 3 и возвращает `false`

    Замена возвращаемых значений блоком finally распространяется в том числе и на исключения, которые выбрасываются или перевыбрасываются в блоке catch:

    function f() {
      try {
        throw "bogus";
      } catch(e) {
        console.log('caught inner "bogus"');
        throw e;      // приостанавливается до завершения блока `finally`
      } finally {
        return false; // заменяет предыдущий `throw`
      }
      // `return false` выполняется сейчас
    }
    
    try {
      f();
    } catch(e) {
      // Не выполняется, т.к. `throw` в `catch `заменяется на `return` в `finally`
      console.log('caught outer "bogus"');
    }
    
    // В результате отображается сообщение caught inner "bogus"
    // и возвращается значение `false`

    Вложенные инструкции try...catch

    Вы можете вкладывать инструкции try...catch друг в друга. Если внутренняя инструкция try...catch не имеет блока catch, то исключение будет перехвачено во внешнем блоке catch.

    Использование объекта Error

    В зависимости от типа ошибки вы можете использовать свойства name и message, чтобы получить более подробную информацию. Свойство name содержит название ошибки (например, DOMException или Error), свойство message — описание ошибки.

    Если вы выбрасываете собственные исключения, то чтобы получить преимущество, которое предоставляют эти свойства (например, если ваш блок catch не делает различий между вашими исключениями и системными), используйте конструктор Error. Например:

    function doSomethingErrorProne () {
      if ( ourCodeMakesAMistake() ) {
        throw ( new Error('The message') );
      } else {
        doSomethingToGetAJavascriptError();
      }
    }
    
    try {
      doSomethingErrorProne();
    } catch (e) {
      console.log(e.name);    // 'Error'
      console.log(e.message); // 'The message' или JavaScript error message
    }

    Объект Promise

    Начиная с ECMAScript 6, JavaScript поддерживает объект Promise, который используется для отложенных и асинхронных операций.

    Объект Promise может находиться в следующих состояниях:

    • ожидание (pending): начальное состояние, не выполнено и не отклонено.
    • выполнено (fulfilled): операция завершена успешно.
    • отклонено (rejected): операция завершена с ошибкой.
    • заданный (settled): обещание выполнено или отклонено, но не находится в состоянии ожидания.

    Загрузка изображения при помощи XHR

    Простой пример использования объектов Promise и XMLHttpRequest для загрузки изображения доступен в репозитории MDN promise-test на GitHub. Вы также можете посмотреть его в действии. Каждый шаг прокомментирован, что позволяет вам разобраться в архитектуре Promise и XHR. Здесь приводится версия без комментариев:

    function imgLoad(url) {
      return new Promise(function(resolve, reject) {
        var request = new XMLHttpRequest();
        request.open('GET', url);
        request.responseType = 'blob';
        request.onload = function() {
          if (request.status === 200) {
            resolve(request.response);
          } else {
            reject(Error('Image didn\'t load successfully; error code:' 
                         + request.statusText));
          }
        };
        request.onerror = function() {
          reject(Error('There was a network error.'));
        };
        request.send();
      });
    }

    Метки документа и участники

    Метки: 
    Contributors to this page: uleming, IgorGilyazov, fscholz, teoli
    Обновлялась последний раз: fscholz,
    Скрыть боковую панель