Мастер Юан-Ма, «Книга программирования».
Программа – это кристаллизованная мысль. Иногда мысли путаются. Иногда при превращении мыслей в программу в код вкрадываются ошибки. В обоих случаях получается повреждённая программа.
Недостатки в программах обычно называют ошибками. Это могут быть ошибки программиста или проблемы в системах, с которыми программа взаимодействует. Некоторые ошибки очевидны, другие – трудноуловимы и могут скрываться в системах годами.
Часто проблема возникает в тех ситуациях, возникновение которых программист изначально не предвидел. Иногда этих ситуаций нельзя избежать. Когда пользователя просят ввести его возраст, а он вводит «апельсин», это ставит программу в непростую ситуацию. Эти ситуации необходимо предвидеть и как-то обрабатывать.
В случае ошибок программистов наша цель ясна. Нам надо найти их и исправить. Таковые ошибки варьируются от простых опечаток, на которые компьютер пожалуется сразу же, как только увидит программу, до скрытых ошибок в нашем понимании того, как программа работает, которые приводят к неправильным результатам в особых случаях. Ошибки последнего рода можно искать неделями.
Разные языки по-разному могут помогать вам в поиске ошибок. К сожалению, JavaScript находится на конце этой шкалы, обозначенном как «вообще почти не помогает». Некоторым языкам надо точно знать типы всех переменных и выражений ещё до запуска программы, и они сразу сообщат вам, если типы использованы некорректно. JavaScript рассматривает типы только во время исполнения программ, и даже тогда он разрешает делать не очень осмысленные вещи без всяких жалоб, например
x = true * "обезьяна"
На некоторые вещи JavaScript всё-таки жалуется. Написание синтаксически неправильной программы сразу вызовет ошибку. Другие ошибки, например вызов чего-либо, не являющегося функцией, или обращение к свойству неопределённой переменной, возникнут при выполнении программы, когда она сталкивается с такой бессмысленной ситуацией.
Но часто ваши бессмысленные вычисления просто породят NaN
(not a number) или undefined
. Программа радостно продолжит, будучи уверенной в том, что она делает что-то осмысленное. Ошибка проявит себя позже, когда такое фиктивное значение уже пройдёт через несколько функций. Она может вообще не вызвать сообщение об ошибке, а просто привести к неправильному результату выполнения. Поиск источника таких проблем – сложная задача.
Процесс поиска ошибок (bugs) в программах называется отладкой (debugging).
Строгий режим (strict mode)
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
, которая настолько ужасна, что даже не обсуждается в этой книге).
Читать дальше