Разработка и Конфигурация · 9 мин
В чем отличие процедуры от функции в 1С
Процедура и функция в 1С: ключевые отличия, возврат значения, области видимости, директивы компиляции и практические примеры кода для разработчика.
В языке 1С:Предприятие процедуры и функции — это именованные блоки кода, которые можно вызывать из других мест программы. Оба конструкта принимают параметры, содержат тело с операторами и помогают структурировать код. Разница между ними принципиальна и влияет на то, как код будет использоваться в выражениях.
Функция обязана вернуть значение через оператор Возврат, процедура — нет. Из этого следуют все остальные отличия: функцию можно вставить в любое выражение (условие, присваивание, арифметику), а процедуру можно вызвать только отдельным оператором. Непонимание этого различия — частая причина ошибок компиляции у начинающих разработчиков.
Синтаксис объявления: как выглядят процедура и функция
Обе конструкции объявляются схожим образом. Процедура начинается ключевым словом Процедура и заканчивается словом КонецПроцедуры, функция — соответственно Функция и КонецФункции. Параметры в круглых скобках указываются одинаково, поддерживаются значения по умолчанию и передача по ссылке через Знач.
Функция РассчитатьСкидку(Сумма, Процент = 10)
Возврат Сумма * Процент / 100;
КонецФункции
Процедура ЗаписатьВЖурнал(ТекстСобытия)
ЗаписьЖурналаРегистрации("МоеПриложение", , , , ТекстСобытия);
КонецПроцедуры
Обратите внимание: в функции присутствует оператор Возврат со значением. В процедуре оператор Возврат тоже допустим, но только без значения — он используется для досрочного выхода из тела. Если попытаться написать Возврат 100; внутри процедуры, конфигуратор выдаст ошибку при проверке модуля.
Главное отличие: возвращаемое значение и использование в выражениях
Ключевое различие — возможность участвовать в выражениях. Вызов функции подставляется в любое место, где ожидается значение: в правую часть присваивания, в условие Если, в арифметическое выражение, в параметр другой функции. Вызов процедуры — всегда самостоятельный оператор, который ничего не «подставляет».
// Корректно: функция внутри выражения
ИтоговаяСумма = СуммаДокумента - РассчитатьСкидку(СуммаДокумента);
Если РассчитатьСкидку(СуммаДокумента) > 1000 Тогда
Сообщить("Крупная скидка");
КонецЕсли;
// Корректно: процедура отдельным оператором
ЗаписатьВЖурнал("Документ проведен");
Обратная ситуация — ошибка. Строка Результат = ЗаписатьВЖурнал("текст"); не скомпилируется, потому что процедура не возвращает значение. Точно так же нельзя просто вызвать функцию как оператор и проигнорировать результат — строгой ошибки это не даст, но считается плохим стилем: если результат не нужен, вероятно, это должна быть процедура.
Сравнение вариантов
Подходит для действий без результата: записи в журнал, установки реквизитов, вывода сообщений. Нельзя использовать в выражениях.
Подходит, когда нужен результат: расчёт, поиск, проверка условия. Можно встраивать в любые выражения и условия.
Что вернуть, если результат не нужен: типичные сценарии
На практике разработчик часто сомневается, что выбрать. Простое правило: задайте вопрос «нужно ли мне после вызова получить какое-то значение?». Если да — функция. Если код только что-то делает (записывает, отправляет, устанавливает) — процедура.
Когда однозначно функция
Расчёты и преобразования: вычисление НДС, форматирование строки, поиск элемента справочника по коду. Проверки с булевым результатом: ДокументЗаполненКорректно(), ЕстьПраваНаИзменение(). Получение данных: ПолучитьКурсВалюты(), НайтиКонтрагентаПоИНН().
Когда однозначно процедура
Действия-обработчики: заполнение табличной части, установка видимости элементов формы, запись в журнал регистрации, отправка уведомления. Обработчики событий формы и объектов (ПриОткрытии, ПередЗаписью) по умолчанию создаются как процедуры, потому что платформа не ждёт от них возвращаемого значения.
Как выбрать действие
Общие свойства: параметры, директивы, экспортность
Кроме возвращаемого значения, процедуры и функции ведут себя одинаково. Обе поддерживают параметры со значениями по умолчанию, ключевое слово Знач для передачи по значению, модификатор Экспорт для доступа из других модулей и директивы компиляции в модулях форм: &НаКлиенте, &НаСервере, &НаСервереБезКонтекста.
Директивы компиляции не зависят от того, процедура это или функция. Метод &НаКлиенте не может вызвать метод &НаСервереБезКонтекста напрямую без серверного вызова — это ограничение контекста, а не типа метода. Асинхронные методы (Асинх) также могут быть как процедурами, так и функциями: асинхронная функция возвращает Обещание.
Типичные ошибки при выборе и использовании
Самая распространённая ошибка — забыть оператор Возврат в функции или покрыть не все ветки логики. Если в функции есть условие и возврат происходит только внутри Если, то при невыполнении условия функция вернёт Неопределено. Это не вызовет ошибки компиляции, но приведёт к трудноуловимым сбоям в местах вызова.
Вторая группа ошибок — попытка использовать процедуру в выражении или присвоить её результат переменной. Конфигуратор отловит это при проверке модуля, но при динамическом выполнении через Выполнить() ошибка всплывёт только в рантайме. Третья ошибка — функция, которая на самом деле меняет данные: вызывающий код ожидает чистый расчёт, а получает побочный эффект в виде изменённого объекта.
Как проверить корректность кода
После написания метода выполните проверку модуля в конфигураторе (меню «Конфигурация» → «Проверка конфигурации» или синтаксический контроль модуля). Ошибки типа «процедура используется как функция» выявляются на этом этапе. Для проверки возвращаемых значений полезно временно вывести результат через Сообщить() или посмотреть его в отладчике.
Как проверить результат
Каждый путь выполнения заканчивается Возврат со значением
Есть путь без Возврат — функция вернёт Неопределено
Функция вызывается в выражении, процедура — отдельным оператором
Процедура стоит в правой части присваивания
Функция только вычисляет и возвращает
Функция меняет объекты или пишет в базу без явной необходимости
Что важно запомнить
Функция возвращает значение и встраивается в выражения, процедура выполняет действие и вызывается отдельным оператором. В остальном — параметры, экспортность, директивы компиляции — они идентичны. Выбирайте по ответу на вопрос: нужен ли результат в точке вызова.
Частые вопросы
Может ли процедура вернуть значение через параметр?
Да. Параметры в 1С по умолчанию передаются по ссылке, поэтому процедура может изменить значение переданной переменной, и вызывающий код увидит изменение. Это легальный приём, но он менее читаем, чем возврат из функции, — используйте его осознанно, например когда нужно вернуть несколько значений через структуру-параметр.
Что вернёт функция, если в ней нет оператора Возврат?
Функция вернёт значение Неопределено. Ошибки компиляции при этом не возникает, поэтому такой дефект легко пропустить. Всегда проверяйте, что все ветки логики функции завершаются оператором Возврат с осмысленным значением.
Можно ли вызвать функцию и проигнорировать её результат?
Технически да — вызов функции отдельным оператором не вызовет ошибку. Но это плохой стиль: если результат не нужен, вероятно, метод стоит оформить как процедуру, либо вы явно теряете важную информацию, например признак ошибки.
Чем обработчики событий отличаются от обычных процедур?
Обработчики событий (ПриОткрытии, ПередЗаписью и другие) — это обычные процедуры, которые платформа вызывает автоматически при наступлении события. Создавать их лучше через палитру свойств формы или объекта: конфигуратор сам сформирует заготовку с правильным набором параметров.
Может ли асинхронный метод быть функцией?
Да. Асинхронная функция (объявленная с ключевым словом Асинх) возвращает объект типа «Обещание», а фактический результат получают через Ждать или обработку обещания. Асинхронная процедура тоже возможна — она просто выполняет действия без итогового значения.
Как передать несколько результатов из одного метода?
Самый читаемый способ — функция, возвращающая Структуру с именованными полями. Альтернатива — процедура, меняющая параметры, переданные по ссылке, но такой код сложнее отлаживать. Массив для возврата нескольких значений используют реже, так как смысл элементов по индексам неочевиден.