Javascript.RU

Конструкции языка. Обработка ошибок.

Update: Более новый материал по этой теме находится по адресу https://learn.javascript.ru/while-for.

Раздел иллюстрирует особенности управляющих конструкций javascript, таких как while/for, switch и обработку исключений.

Две формы while:

// проверка вначале
while(i<5) { … }
// условие потом
do { … } while (i<5)

И две принципиально разные формы for. Одна - обычная:

// заметьте - новая переменная объявлена тут же
for (var i=0;i<10;i++) {
   ...
}

Другая - итерация по свойствам объекта:

for(key in obj) {
  ... obj[key]
}

Можно исключить унаследованные свойства (т.е исключить из цикла прототип). Для этого используем функцию hasOwnProperty:

// цикл только по собственным свойствам
for(var key in obj) {
  if (obj.hasOwnProperty(key)) {
    … obj[key] …
  }
}

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

Метки действуют только для циклов и switch, т.е организовать полноценный goto через них нельзя Sad

На метку внешнего цикла можно перейти при помощи break/continue, вот пример:

// внешний цикл
outer: for(…) {
	…
	// внутренний цикл
	for (…) {
		…
		// можно вывалиться из внешнего цикла
		break outer;
		…
		// или перейти на следующую итерацию внешнего цикла
		continue outer;
		…
	}
}

В некоторых языках можно сделать только switch(число/строка).

В javascript же конструкция switch принимает совершенно любой объект. Перед switch, как и перед циклами можно ставить метку, и делать break/continue на внешнюю метку.

switch (obj) {
case "test":
	…
	break
case 5:
	…
	break outer
default: 
	…
}

With - специфическая конструкция javascript, самый известный ее аналог - with в Pascal/Delphi. Поэтому мы остановимся на ней подольше.

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

Более подробно тема видимости разобрана в статье функции Javascript, а здесь - разберем конкретно то, что с ней делает with.

Коротко - with берет объект и делает из него новую вложенную область видимости.

Например, в некоторой функции:

function go() {
...
var obj

// obj будет браться из текущей области видимости
obj.size = 5
...
}

Создадим тестовый объект, но не просто var obj, а более развернуто:

obj_size

(Более подробно об определении и свойствах объекта написано в разделе Объекты, ООП)

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

В этом примере свойства weight и size будут взяты из объекта obj:

with (obj) {
	// width/height берутся из найденного size
	return weight / (size.width + size.height)
}

А здесь - with делает область видимости из obj.size:

with (obj.size) {
	return width + height
}

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

Типичный пример из реальной жизни:

with (div.style) {
	if (!browser.isSafari) {
		position = 'absolute'
	}
	left = 0
	right = 0
	visibility = 'hidden'	
}

Напомню, что интерпретатор javascript ищет все переменные в ближайшей области видимости. Если не находит - ищет в следующей, и так далее - до глобальных переменных, т.е window.
Поэтому можно, например, делать конструкции типа такой:

with (obj) {
	with (size) {
		return weight / (width + height)
	}
}

Здесь переменные из разных областей видимости используются в одном выражении.

with javascript

Область видимости size находится внутри obj, поэтому интерпретатор будет искать weight так:

  1. сначала посмотрит weight в size
  2. не найдет там такой переменной
  3. посмотрит weight в obj
  4. использует weight из obj

Работа с with(obj) не эквивалентна работе напрямую с объектом obj, т.к никаких новых переменных добавить в obj нельзя.

Например, сделаем тестовый объект:

obj = {
	weight: 100
}

mwsnap010.jpg

Внутри with можно получить weight, и даже поменять его значение:

javascript with

Но вот при попытке добавить переменную возникнет проблема:

mwsnap012.jpg

Сам объект не поменялся, зато перезаписали глобальную переменную

alert(obj.size)   // => undefined
alert(window.size)   // => 10

У with есть одна большая проблема, из-за которой многие вообще рекомендуют забыть эту конструкцию.

А именно - внутри блока with абсолютно нельзя сказать, откуда будет взята та или иная переменная.

Выше разобран пример, когда weight ищется сначала в size, затем в obj, и потом - в глобальной области window.
Если переменной не окажется там, где она по плану должна быть, то она будет взята/изменена в другой области видимости, возможно даже в глобальной window.

Это приводит к трудноуловимым ошибкам, поэтому часто используют альтернативу: временную переменную.

mwsnap013.jpg

С другой стороны, синтаксис with удобнее и полезен там, где ошибок уж точно не может быть. Например, при манипуляции стилями.

Работа с исключениями в javascript организована в типичном для языка стиле вседозволенности.

Абсолютно любой объект можно бросить в виде исключения:

try {
  ...
  throw {message: "Ого!"}
  ..
} catch (e) {
  alert("Ага, попался!")
}

Обычно бросают, все же, не простые объекты, а потомки встроенного класса Error:

throw new Error("connection down, server timeout")
// или сделать наследника Error:
throw new ConnectionError("server timeout")

Встроенный класс Error удобен для унификации проверки "a instanceof Error" и интероперабельности с другими библиотеками, так как ничего полезного в нем часто нет.

В Firefox у объекта Error есть полный бэктрейс в свойстве stack и еще масса полезных свойств:

// так можно быстро узнать стек без отладчика
alert( (new Error()).stack )

В IE тоже есть некоторые полезные свойства, а в Opera/Safari - на момент написания только message:

var e = new Error("hi")
alert(e.message)  // => "hi"

Поэтому, например, у меня созданы потомки (синтаксис фреймворка dojo):

// базовый класс для ошибок, со стеком (Firefox)
// сообщением message и дополнительной информацией extra
dojo.declare(
	"dojo.Error",
	Error,
	function(message, extra) {
		this.message = message;
		this.extra = extra;
		this.stack = (new Error()).stack;	
	}
)
// Потомок, имя ошибки хранится в name
// формат: dojo.declare(Имя, Родитель, Конструктор)
dojo.declare(
	"dojo.CommunicationError",
	dojo.Error,
	function() {
		this.name="CommunicationError";
	}
)

// еще потомок для примера
dojo.declare(
	"dojo.LockedError",
	dojo.Error,
	function() {
		this.name="LockedError";
	}
)
...

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

try {
	… код ...
} catch(e) {
	// ловим нужное исключение
	if (e instanceof ConnectionError) {
		// обрабатываем его
		… reconnect …
	} else {
		// пробрасываем незнакомое исключение дальше
		throw e
	}
		
} finally {
	// блок finally выполняется всегда, 
	// вне зависимости - было исключение или нет
	… notifyUser() ..
}

В этом примере также присутствует блок finally, взятый в javascript из java. В стандартной схеме try..catch..finally, код из блока finally выполняется либо после try, если эксепшна нет, либо после catch, даже если эксепшн выпал наружу.

Короче говоря, код в finally выполнится при любом результате работы try/catch, и туда удобно ставить всякие очистки, уведомления о конце процесса и т.п.


Автор: UFABET168GO (не зарегистрирован), дата: 17 ноября, 2023 - 14:22
#permalink

ทางเข้าufabet168 เว็บตรง เสถียร ใช้งานง่ายที่สุด


Автор: nathalie590 (не зарегистрирован), дата: 20 ноября, 2023 - 13:08
#permalink

You can also download latest APKs, like Zaxiusdomain


Автор: Jacob59042 (не зарегистрирован), дата: 20 ноября, 2023 - 13:15
#permalink

You can also download these injectors to enhance your MLBB game experience.


Автор: betflixvip (не зарегистрирован), дата: 20 ноября, 2023 - 13:33
#permalink

Great post! I am actually getting ready to across this information, is very helpful my friend. I also like to recommend a site that is all about buy telegram members. Keep up the good work you are doing here. betflixvip


Автор: sad (не зарегистрирован), дата: 21 ноября, 2023 - 18:17
#permalink

인천오피
I am really enjoying reading your well written articles. It looks like you spend a lot of effort and time on your blog. I have bookmarked it and I am looking forward to reading new articles. Keep up the good work.


Отправить комментарий

Приветствуются комментарии:
  • Полезные.
  • Дополняющие прочитанное.
  • Вопросы по прочитанному. Именно по прочитанному, чтобы ответ на него помог другим разобраться в предмете статьи. Другие вопросы могут быть удалены.
    Для остальных вопросов и обсуждений есть форум.
P.S. Лучшее "спасибо" - не комментарий, как все здорово, а рекомендация или ссылка на статью.
Содержание этого поля является приватным и не предназначено к показу.
  • Адреса страниц и электронной почты автоматически преобразуются в ссылки.
  • Разрешены HTML-таги: <strike> <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd> <u> <i> <b> <pre> <img> <abbr> <blockquote> <h1> <h2> <h3> <h4> <h5> <p> <div> <span> <sub> <sup>
  • Строки и параграфы переносятся автоматически.
  • Текстовые смайлы будут заменены на графические.

Подробнее о форматировании

CAPTCHA
Антиспам
2 + 9 =
Введите результат. Например, для 1+3, введите 4.
 
Текущий раздел
Поиск по сайту
Содержание

Учебник javascript

Основные элементы языка

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

Интерфейсы

Все об AJAX

Оптимизация

Разное

Дерево всех статей

Последние комментарии
Последние темы на форуме
Forum