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

x = true * "обезьяна"

На некоторые вещи JavaScript всё-таки жалуется. Написание синтаксически неправильной программы сразу вызовет ошибку. Другие ошибки, например вызов чего-либо, не являющегося функцией, или обращение к свойству неопределённой переменной, возникнут при выполнении программы, когда она сталкивается с такой бессмысленной ситуацией.

Но часто ваши бессмысленные вычисления просто породят NaN (not a number) или undefined. Программа радостно продолжит, будучи уверенной в том, что она делает что-то осмысленное. Ошибка проявит себя позже, когда такое фиктивное значение уже пройдёт через несколько функций. Она может вообще не вызвать сообщение об ошибке, а просто привести к неправильному результату выполнения. Поиск источника таких проблем – сложная задача.

Процесс поиска ошибок (bugs) в программах называется отладкой (debugging).

<p>Строгий режим (strict mode)</p>

JavaScript можно заставить быть построже, переведя его в строгий режим. Для этого наверху файла или тела функции пишется "use strict". Пример:

function canYouSpotTheProblem() {

  "use strict";

  for (counter = 0; counter < 10; counter++)

    console.log("Всё будет офигенно");

}

canYouSpotTheProblem();

// → ReferenceError: counter is not defined

Обычно, когда ты забываешь написать var перед переменной, как в примере перед counter, JavaScript по-тихому создаёт глобальную переменную и использует её. В строгом режиме выдаётся ошибка. Это очень удобно. Однако, ошибка не выдаётся, когда глобальная переменная уже существует – только тогда, когда присваивание создаёт новую переменную.

Ещё одно изменение – привязка this содержит undefined в тех функциях, которые вызывали не как методы. Когда мы вызываем функцию не в строгом режиме, this ссылается на объект глобальной области видимости. Поэтому если вы случайно неправильно вызовете метод в строгом режиме, JavaScript выдаст ошибку, если попытается прочесть что-то из this, а не будет радостно работать с глобальным объектом.

К примеру, рассмотрим код, вызывающий конструктор без ключевого слова new, в случае чего this не будет ссылаться на создаваемый объект.

function Person(name) { this.name = name; }

var ferdinand = Person("Евлампий"); // ой-вэй

console.log(name);

// → Евлампий

Некорректный вызов Person успешно происходит, но возвращается как undefined и создаёт глобальную переменную name. В строгом режиме всё по-другому:

"use strict";

function Person(name) { this.name = name; }

// Опаньки, мы ж забыли 'new'

var ferdinand = Person("Евлампий");

// → TypeError: Cannot set property 'name' of undefined

Нам сразу сообщают об ошибке. Очень удобно.

Строгий режим умеет ещё кое-что. Он запрещает вызывать функцию с несколькими параметрами с одним и тем же именем, и удаляет некоторые потенциально проблемные свойства языка (например, инструкцию with, которая настолько ужасна, что даже не обсуждается в этой книге).

Короче говоря, надпись "use strict" перед текстом программы редко причиняет проблемы, зато помогает вам видеть их.

<p>Тестирование</p>

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

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

Для примера вновь обратимся к типу Vector.

function Vector(x, y) {

  this.x = x;

  this.y = y;

}

Vector.prototype.plus = function(other) {

  return new Vector(this.x + other.x, this.y + other.y);

};

Перейти на страницу:

Похожие книги