Что такое verbose в консоли браузера
Метод console.log() — отличный способ вывести отладочную информацию, не мешая пользователю. Но знаете ли Вы, что объект console имеет еще уйму других не менее полезных методов? Очень редко разработчики используют этот функционал, ограничиваясь неблокирующим alert'ом. Что-ж, давайте исправим это положение.
Небольшое примечание: использование отладочного кода может негативно сказаться на производительности. Удаляйте его из продакшн версии.
Перед тем, как погрузиться в малоизвестные методы console, рассмотрим функционал console.log подробнее. Например, возможность передачи любого числа аргументов:
Если Вы знакомы с функцией printf() в других языках, то спешим обрадовать: console.log() умеет вести себя похожим образом. Возьмем последний пример и передадим первый аргумент в немного измененном виде.
Что за %s?
Отличный вопрос! Это управляющие последовательности, которые заменяются на соответствующие им значения (в порядке очередности). %s означает «трактовать значение как строку», %d — как число (Также можно использовать %i или %f).
Каждое вхождение такой последовательности будет заменено на следующий по порядку аргумент. Первое вхождение — на первый (за первым аргументом-строкой, конечно), ну и так далее.
Порядок использования аргументов можно изменить вручную, использовав символ $ и приписав перед ним номер аргумента, который мы хотим вывести:
Эта команда как бы говорит «Я начну со второго аргумента и продолжу, начиная со следующего». Как Вы видите, последовательности, которым не хватило аргументов, остались нетронутыми.
Первый аргумент (строка формата) также участвует в нумерации (она идет с нуля) аргументов. Таким образом, в нашем примере последний аргумент будет иметь номер 5. Но мы задали всего 5 аргументов и, при этом, начали со второго. Поэтому, последней управляющей последовательности аргументов не досталось, и она не изменилась.
Для того, чтобы аргументы были выведены правильно, нам нужно изменить порядок вывода второго и третьего элементов. Другие элементы и так в правильном положении, так что нет необходимости указывать их позиции. Аргументы будут использованы в следующем порядке: 2, 1, 3, 4, 5.
Форматирование строк — мощный инструмент, и я охватил только вершину айсберга. Попробуйте поиграться самостоятельно и почитать, что пишет Joe Hewitts о консоли.
Есть еще пара методов, подобных log, но отличающихся внешне. А именно: console.info(), console.warn() и console.error().
console.info(), console.warn() и console.error() в Firebug'е.
Все три метода умеют выводить строки в соответствие с форматом и принимать любое количество аргументов.
Логи DOM'а
Когда Вам нужно как-то указать в логах на DOM узел лучшего всего использовать методы console.dir() или console.dirxml(), которые могут перечислить свойства элемента или вывести HTML кода элемента.
Знакомьтесь: console.dir() и console.dirxml() в Chrome.
Группировка
Иногда бывает полезно сгруппировать логи для упрощения работы с ними. Для этого существуют методы console.group(), console.groupCollapsed() и console.groupEnd().
Группировка в консоли Safari.
Как Вы можете видеть, подряд идущие вызовы group создают вложенные папки. Чтобы закрывать папку, используйте метод console.groupEnd(). Метод console.groupCollapsed() аналогичен console.group() за тем лишь исключением, что группа со всем содержимым будет изначально свернута.
Профилирование и замеры
Также консоль позволяет точно замерять время, используя метод console.time() и console.timeEnd(). Расположите вызов первого из них перед кодом, время исполнения которого хотите замерить, а второго — после.
Пример работы console.time() и console.timeEnd() в Firefox
Помимо замера времени можно профилировать Ваш код и вывести стек профилирования, который подробно показывает, где и сколько времени потратил браузер.
Профилирование в Chrome.
Assert'ы
Когда Вы работаете над сложным проектом, важно покрывать код юнит тестами. Это позволит избежать глупых ошибок и возможных регрессий. К счастью, консоль включает в себя assert'ы.
Assert'ы позволяют обеспечивать соблюдение правил в коде и быть уверенным, что результаты выполнения этого кода соответствуют ожиданиям. Метод console.assert() позволяет проводить элементарное тестирование кода: если что-то пойдет не так, будет выброшено исключение. Первым аргументом может быть все, что угодно: функция, проверка на равенство или проверка существования объекта.
Assert в Chrome
Поддержка браузерами
Большинство перечисленных методов поддерживаются достаточно хорошо. IE8+, Firefox с расширением firebug, Opera или webkit-браузер вроде Safari или Chrome. Есть, правда, некоторые различия: Firefox, Safari и Chrome отличаются более широкой поддержкой. Проще всего проверить совместимость можно выполнив console.dir(console), результатом которого будет вывод объекта console со всеми его методами.
Opera с Dragonfly поддерживает большинство методов, за исключением форматирования строк и профилирования (хотя методы profile, profileEnd и реализованы, это всего лишь заглушки).
IE8 также поддерживает много вкусностей, включая форматирование строк и assert'ы, но не замеры времени, профилирование, методы dir или dirxml.
Стоит отметить, что firebug lite может добавить некоторые методы к console в браузерах, их не поддерживающих.
Это не полный список того, что есть в console, но я перечислил наиболее полезные возможности, существенно упрощающие процесс отладки и тестирования. Используйте приобретенные знания и не ограничивайтесь одним лишь логированием строк.
Extra
Итак, это был очень вольный перевод статьи, но теперь я бы хотел добавить немного от себя:
Node.JS (ветка 0.2) поддерживает методы log, info, warn, error, dir, time / timeEnd, assert и trace.
log не умеет изменять порядок аргументов для подстановок, но сами подстановки реализованы. При вызове метода trace в консоль будет выведен стек вызовов (все методы ничего не возвращают, а просто пишут в консоль). Работает это также как минимум в Chrome и Opera.
В Opera и Chrome, помимо уже перечисленных, реализованы следующие методы:
count — выводит, сколько раз уже выполнялась строка, на которой расположен вызов метода. Аргументом передается строка, которая будет выведена перед количеством вызовов.
debug — ничем не отличается от log.
В Опере также есть метод table, который должен строить красивую табличку из аргументов, но ничего не делает.
Вообще, Опера немного странновата. Результаты работы обсуждаемых функций нужно искать не в стандартной консоли, а на просторах Dragonfly (впрочем, это логично). Причем часть из них можно найти сразу в двух местах: на вкладке «Консоль ошибок» и «Скрипты» -> REPL.
Также в Chrome у объекта console есть свойство memory, являющееся объектом со свойствами totalJSHeapSize и usedJSHeapSize. Однако, в Chromium'е мне так и не удалось застать эти свойства со значениями, отличными от нуля.
По умолчанию любая именованная функция, имеющая атрибут [CmdletBinding()], принимает параметры -debug и -verbose (и несколько других) и имеет предопределенные переменные $debug и $verbose . Я пытаюсь выяснить, как передать их другому командлету, который вызывается внутри функции.
Допустим, у меня есть такой командлет:
Если в мою функцию были переданы -debug или -verbose , я хочу передать этот флаг в командлет new-item . Какой правильный шаблон для этого?
ОТВЕТЫ
Ответ 1
Возможно, это звучит странно, но для командлета не существует простого способа узнать его подробный режим или режим отладки. Посмотрите на связанный вопрос:
Один не идеальный, но практически разумный вариант - ввести собственные параметры командлета (например, $MyVerbose и $MyDebug ) и явно использовать их в коде:
UPDATE
Когда нам нужен только переключатель (не скажем, значение уровня многословия), тогда подход с $PSBoundParameters , возможно, лучше, чем предложенный в первой части этого ответа (с дополнительными параметрами):
Всё равно не идеально. Если есть лучшие решения, то я бы очень хотел узнать их сам.
Ответ 2
$PSBoundParameters - это не то, что вы ищете. Использование атрибута [CmdletBinding()] позволяет использовать $PSCmdlet в вашем script, помимо предоставления флага Verbose. На самом деле это то же самое, что вы должны использовать.
Через [CmdletBinding()] вы можете получить доступ к связанным параметрам с помощью $PSCmdlet.MyInvocation.BoundParameters . Здесь функция, которая использует CmdletBinding, и просто сразу вводит вложенное приглашение, чтобы проверить переменные, доступные внутри области функций.
Итак, в вашем примере вам понадобится следующее:
Это охватывает -Verbose, -Verbose: $false, -Verbose: $true и случай, когда переключатель вообще отсутствует.
Ответ 3
Нет необходимости. PowerShell уже делает это, как показано ниже.
Это не делается так же прямо, как передача -Debug для следующего командлета. Это делается через переменные $DebugPreference и $VerbrosePreference. Write-Debug и Write-Verbose действуют так, как вы ожидали, но если вы хотите сделать что-то другое с помощью отладки или подробного описания, вы можете прочитать здесь, как проверить себя.
Ответ 4
Вот мое решение:
Чем это отличается от других примеров, так это тем, что оно будет отображать "-Verbose: $ false" или "-Debug: $ false". Для -Verbose / -Debug будет установлено значение $ true, только если вы используете следующее:
Ответ 5
Вы можете создать новую хеш-таблицу на основе связанных параметров debug или verbose, а затем поместить ее во внутреннюю команду. Если вы просто указываете ключи (и не передаете ложный переключатель, например $debug: $false), вы можете просто проверить наличие отладки или подробного:
Если вы хотите передать значение параметра, это сложнее, но может быть выполнено с помощью
Ответ 6
Лучший способ сделать это - установить $VerbosePreference . Это включит подробный уровень для всего сценария. Не забудьте отключить его в конце скрипта.
Ответ 7
Вы можете установить VerbosePreference в качестве глобальной переменной при запуске script, а затем проверить глобальную переменную в своем настраиваемом командлете.
Проверка явно для "Продолжить" позволяет script быть равно -verbose:$false при вызове CmdLet из script, который не устанавливает глобальную переменную (в этом случае она $null )
Данный параметр предназначен в общем случае для подавления запросов на проведение каких-то операций. Например, запрос на перезапись существующего файла.
Предназначен для эмуляции выполнения команды и вывода информации, о том, что бы случилось, если выполнить данную команду без этого параметра. Для примера можете посмотреть вывод команды:
Если ваш скрипт выполняет какие-то деструктивные действия, имеет смысл включить этот параметр в ваш скрипт для возможности проверки, что будет выполнено именно то, что нужно.
Если ваш скрипт выполняет какие-то серьёзные и/или деструктивные действия (например, как командлет Set-ExecutionPolicy), следует применять параметр Confirm.
Определение этих параметров в коде
Применение этих параметров в простых функциях (не advanced) по сути сводится к написанию собственных обработчиков этих параметров. В Advanced functions появилась возможность универсально обрабатывать эти параметры. Вот пример кода:
И вот вывод какое у нас получится поведение:
В данном случае предполагается, что функция выполняет деструктивные действия, поэтому по умолчанию мы выводим запрос о подтверждении операции по умолчанию. Если укажем WhatIf, мы увидим, что бы случилось при обычном запуске (с подтвеждением операции). Но если мы хотим выполнить операцию без всяких подтверждений, мы используем параметр Force.
Как мы добились такого поведения? Во-первых, конструкция в начале скрипта [CmdletBinding()] определяет общее поведение всего скрипта. У него есть разные атрибуты. В данном случае были использованы:
Этот атрибут указывает, должен ли код ожидать ответ от пользователя на выполнение операции. Т.е. он включает обработчик для параметров –Confirm и –WhatIf.
Этот атрибут указывает уровень воздействия кода на систему и включает обработчик параметра –Confirm. Возможные значения:
По умолчанию в сессии PowerShell уровень воздействия выставлен в High (можно посмотреть в переменной $ConfirmPreference). И все командлеты, у которых уровень воздействия на систему выше или такой же, как в $ConfirmPreference, запрос на подтверждение будет выводиться всегда.
Например, в сессии у нас $ConfirmPreference = 'High', а у командлета/функции тоже 'High' будет выведен запрос подтверждения. Как в случае с Set-ExecutionPolicy. Если у командлета/функции ConfirmImpact ниже (Low или Medium) запрос подтверждения по умолчанию выводиться не будет. Но возможно указать –Confirm для принудительного вывода запроса подтверждения. Если посмотреть на наш код, мы увидим, что уровень воздействия на систему высокий, поэтому мы каждый раз получаем запрос подтверждения. Если мы изменим уровень воздействия в уровень 'Medium', наша функция не будет по умолчанию выводить никаких запросов. Но будет выводить его при указании параметра –Confirm:
И вот какое у нас будет поведение:
Теперь запрос выводится только когда мы явно указываем параметр –Confirm. Параметры мы подключили, как реализовать код? Для этого есть специальная переменная $PsCmdlet, которая используется для обработки параметров командлета/функции. У этой переменной есть метод ShouldProcess("Target","Action description"). В аргумент Target указываете название объекта (в нашем случае — имя файла), над которым будет совершено действие, а в Action description пишите, какое действие будет произведено.
Указание параметра –WhatIf и/или –Confirm вызывает метод ShouldProcess и в зависимости от параметров выполняет нужное действие — выводит запрос или эмулирует выполнение команды. Поэтому мы просто засовываем $PSCmdlet.ShouldProcess() в условный оператор IF и в конструкции Then пишем код, который будет выполнять действие.
Чтобы реализовать функционал параметра –Force, я его поместил в то же условие. Причём, он должен проверяться первым. Это связано с тем, что при выполнении оператора –or, сначала проверяется выражение слева от оператора. Если оно возвращает True, выражение справа от оператора не проверяется. Следовательно, если параметр –Force указан, метод ShouldProcess() просто не вызовется.
При распитиинаписании скриптов, весьма целесообразно включать отладочную информацию в скрипт, которую можно посмотреть, если что-то идёт не так. Запомните, НИКАКИХ этих ваших Write-Host или чего-то ещё. Для этого предусмотрены параметры Verbose и Debug. Verbose применяется для вывода на экран общего хода выполнения скрипта. Debug применяется для включения уже детальной отладочной информации и возможно переключение в пошаговое исполнение скрипта. Эти параметры не надо определять в параметрах функции, они автоматически добавляются к коду при использовании конструкции [CmdletBinding()].
Вот как правильно определять поведение этих параметров:
Как мы уже знаем, если указана конструкция [CmdletBinding()], эти параметры автоматически подключаются к функции и мы их не определяем в секции param(). Чтобы отловить эти параметры, мы используем специальную переменную $PSBoundParameters. Более подробней об этой переменной я писал в статье: Cmdlet wrapping и PsBoundParameters. По умолчанию, $VerbosePreference и $DebugPreference = 'SilentlyContinue', т.е. даже при указании этих параметров вы ничего не увидите. Поэтому, если параметр указан при вызове функции, мы переводим их в состояние 'Continue', что включает вывод для Verbose и Debug.
Давайте посмотрим более реальный случай в несферическом вакууме — сброс пароля локального администратора:
И вот вывод в консоли для –Verbose:
Так же, мы видим, что Debug включает пошаговое исполнение скрипта, вне зависимоти от состояния параметра Force. Это только в случае, если у нас включен SupportsShouldProcess.
На сегодня вроде всё.
Categories: PowerShell | Guidelines
Posted at: 27.11.2011 18:38 (GMT+3) by Vadims Podāns | Permalink | Comments (2)
Performance is important for a certain class I'm writing.
I thought about calling a function like so:
And the contents would be like
So I wonder: is this enough for V8 to flag this as "dead code" if the DEBUG variable never changes?
Edit: I'm more worried about the performance in Node than on the browser, so removing the code while minifying would be insufficient.
3 Answers 3
I use comments that when a file is minified get removed, such as:
There's a couple of solutions available(aside Petah's. ):
You can use the --define (-d) switch in order to declare global variables that UglifyJS will assume to be constants (unless defined in scope). For example if you pass --define DEBUG=false then, coupled with dead code removal UglifyJS will discard the following from the output:
UglifyJS will warn about the condition being always false and about dropping unreachable code; for now there is no option to turn off only this specific warning, you can pass warnings=false to turn off all warnings.
Another way of doing that is to declare your globals as constants in a separate file and include it into the build. For example you can have a build/defines.js file with the following:
uglifyjs build/defines.js js/foo.js js/bar.js. -c UglifyJS will notice the constants and, since they cannot be altered, it will evaluate references to them to the value itself and drop unreachable code as usual. The possible downside of this approach is that the build will contain the const declarations.
For example you have this method:
You add logging to it by wrapping it in a logger function:
This way the only performance hit would be at startup time. You can also use AOP method with the above wrapper function:
And you can pass information to the logger by adding properties to the function:
You can have a look at this question where someone created code that creates a logger for functions in an object recursively. Also check this answer of mine.
You can just do something like this:
or something like this
Then you can do this in your code
Or you use it's npm warapper: laudanumscript
I haven't been able to find conditional compilation with sweetjs, but I'm sure it wouldn't be too hard to implement it. The end syntax would be(or should be!) similar to cpp.
Если вы занимаетесь веб-программированием, это значит, что вам не надо рассказывать о том, насколько в вашей работе важна отладка. Нередко для записи данных в логи, для их форматирования или вывода на экран используют внешние библиотеки, не учитывая при этом того факта, что в распоряжении программистов имеются JavaScript-команды для работы с консолями, которые встроены в браузеры. И обладают эти консоли гораздо более серьёзными возможностями, чем может показаться на первый взгляд.
Пожалуй, первое, что многим приходит в голову при слове «консоль» — это команда console.log() . Однако, она — лишь одна из многих подобных команд. Материал, перевод которого мы сегодня публикуем, посвящён особенностям работы с консолью JavaScript.
Что такое консоль?
Консоль JavaScript — это механизм, интегрированный в современные браузеры, который поддерживает встроенные инструменты разработки в интерфейсе, напоминающем командную строку. С использованием консоли разработчик может делать следующее:
- Просматривать журналы ошибок и предупреждений, возникающих на веб-странице.
- Взаимодействовать с веб-страницей, используя команды JavaScript.
- Отлаживать приложения и работать с DOM непосредственно из браузера.
- Исследовать и анализировать сетевую активность.
Методы console.log, console.error, console.warn и console.info
Вероятно, наиболее часто используемыми методами при работе с консолью являются console.log() , console.error() , console.warn() и console.info() . Этим методам можно передавать один или несколько параметров. Система вычисляет значение каждого из них и объединяет все результаты в строку, части которой разделены пробелами. В случае с объектами или массивами эти команды позволяют выводить их в таком виде, который позволяет просматривать их содержимое. Вот как это выглядит.
Использование различных команд для вывода данных в консоль
Метод console.group
Метод console.group() позволяет собирать серии вызовов console.log() (а также — других подобных методов) в группы, содержимое которых можно сворачивать и разворачивать. Пользоваться этим методом очень просто: после вызова console.group() (или после console.groupCollapsed() , если группу требуется вывести сразу в свёрнутом виде) нужно поместить все вызовы console.log() , которые надо сгруппировать. Затем, в конце набора команд, которые требуется сгруппировать, надо поместить команду console.groupEnd() . Рассмотри пример.
В консоль, после выполнения этого фрагмента кода, попадёт следующее.
Группировка данных в консоли с помощью метода console.group()
Метод console.table
После того, как я узнал о существовании метода console.table() , моя жизнь изменилась навсегда. Например, использование обычной команды console.log() при выводе JSON-кода или больших JSON-массивов — это сущий кошмар. Метод console.table() позволяет выводить сложные структуры данных внутри симпатичных таблиц, столбцам которых можно давать имена, передавая их в качестве параметров (не все браузеры поддерживают эту возможность console.table() ). Вот пример работы с этой командой.
То, что получилось, и выглядит отлично, и способно облегчить отладку.
Табличное оформление выводимых данных с помощью console.table()
Методы console.count, console.time и console.timeEnd
Методы console.count() , console.time() и console.timeEnd() можно назвать чем-то вроде швейцарского ножа для разработчика, который занимается отладкой приложений. Так, метод console.count() позволяет подсчитывать количество собственных вызовов и выводить его в консоль с заданной меткой. Метод console.time() позволяет запустить именованный таймер (имя передаётся ему в качестве параметра, на одной странице может присутствовать до 10000 таймеров). Для того чтобы остановить конкретный таймер, используется команда console.timeEnd() с меткой таймера, передаваемой в качестве параметра. Она останавливает таймер и выводит время его работы в консоль. Вот как пользоваться этими методами.
А вот как выглядит результат работы этого кода в консоли.
Использование методов console.count(), console.time() и console.timeEnd()
Методы console.trace и console.assert
Методы console.trace() и console.assert() позволят выводить из места их вызова информацию о стеке. Представьте себе, что вы занимаетесь разработкой JS-библиотеки и хотите сообщить пользователю о том, где возникла ошибка. В подобном случае эти методы могут оказаться весьма полезными. Метод console.assert() похож на console.trace() , разница между ними заключается в том, что console.assert() выведет данные лишь в том случае, если не выполнится переданное ему условие. Вот как работать с этими методами.
Несложно заметить, что вывод, генерируемый этим фрагментом кода, выглядит так же, как нечто подобное выглядело бы в React (или в любой другой библиотеке), когда фреймворк сообщает о возникновении исключения.
Результат использования команд console.assert() и console.trace()
Команды для работы с консолью и продакшн-код
Команды для работы с консолью нужны на этапе разработки и отладки приложений. Это значит, что когда придёт время выпуска продукта, эти команды придётся из кода удалить. Об этом можно просто забыть и, через некоторое время после сборки продакшн-версии проекта, заметить, что программа пишет что-то в консоль тогда, когда в этом нет никакой необходимости. Не стоит нагружать компьютеры ненужной работой, пусть и такой, казалось бы, незначительной, как вывод данных в консоль. В то же время, учитывая то, что команды для работы с консолью могут пригодиться в ходе доработки приложения, лучше всего не удалять их из исходного кода программы насовсем, а убирать их лишь из её продакшн-версии. Тут нам на помощь придут средства для сборки проектов. Так, я постоянно пользуюсь Webpack, и на работе, и в собственных проектах. Этот инструмент позволяет удалять все ненужные команды по работе с консолью (он способен отличить их от других команд) из продакшн-сборок с использованием uglifyjs-webpack-plugin.
Эта конфигурация очень проста, но она облегчает повседневную работу программиста и избавляет от проблемы забытых команд по работе с консолью.
Итоги
В этом материале мы рассказали о некоторых полезных командах для работы с консолью. Они позволяют, с помощью инструментов, являющихся частью современных браузеров, решать множество задач, которые сопутствуют разработке и отладке клиентских JavaScript-приложений.
Читайте также: