Разработка и Конфигурация · 12 мин
Как передать параметры в функцию в 1С
Как передать параметры в функцию 1С: по значению и по ссылке, необязательные параметры, значения по умолчанию, экспортные функции, типичные ошибки и примеры кода.
Параметры функции в 1С — это данные, которые вызывающий код передаёт внутрь функции для обработки. Способ передачи влияет не только на синтаксис вызова, но и на поведение программы: параметр, переданный по ссылке, можно изменить внутри функции, и это изменение увидит вызывающий код, а параметр по значению остаётся нетронутым снаружи. Непонимание этой разницы — одна из самых частых причин трудноуловимых ошибок в конфигурациях.
Встроенный язык 1С поддерживает обязательные и необязательные параметры, значения по умолчанию, ключевое слово «Знач» для принудительной передачи по значению и экспортные функции общих модулей. Ниже разобраны все варианты объявления и вызова с примерами, которые можно перенести в свой код без доработки.
Базовый синтаксис объявления функции с параметрами
Функция объявляется ключевым словом «Функция», после имени в круглых скобках перечисляются параметры через запятую. Функция обязана вернуть значение оператором «Возврат» — в отличие от процедуры, которая ничего не возвращает.
Функция РассчитатьСуммуНДС(СуммаБезНДС, СтавкаНДС)
СуммаНДС = СуммаБезНДС * СтавкаНДС / 100;
Возврат СуммаНДС;
КонецФункции
Вызов такой функции выглядит симметрично: аргументы перечисляются в том же порядке, в котором объявлены параметры. Порядок строго фиксирован — «по имени» аргументы в 1С не передаются, как в некоторых других языках.
НДС = РассчитатьСуммуНДС(100000, 20);
Если функция объявлена без параметров, скобки при объявлении и вызове всё равно обязательны: Функция ПолучитьКурс() и вызов Курс = ПолучитьКурс();. Пропуск скобок при вызове приведёт к тому, что в переменную запишется не результат, а описание метода — частая ошибка новичков.
Передача по значению и по ссылке: ключевое слово «Знач»
По умолчанию параметры передаются по ссылке. Это значит, что функция работает с той же областью памяти, что и вызывающий код: присвоение параметру нового значения внутри функции изменит переменную снаружи. Для примитивных типов (число, строка, дата, булево) это работает напрямую, для объектов вроде структур и массивов — через ссылку на объект.
Функция УвеличитьСчётчик(Счётчик)
Счётчик = Счётчик + 1;
Возврат Счётчик;
КонецФункции
// Вызов:
А = 10;
Результат = УвеличитьСчётчик(А);
// А теперь равно 11, Результат тоже 11
Ключевое слово «Знач» перед именем параметра принудительно включает передачу по значению: внутри функции создаётся копия, и исходная переменная не меняется. Это защищает вызывающий код от побочных эффектов.
Функция УвеличитьСчётчик(Знач Счётчик)
Счётчик = Счётчик + 1;
Возврат Счётчик;
КонецФункции
// Вызов:
А = 10;
Результат = УвеличитьСчётчик(А);
// А осталось 10, Результат = 11
Необязательные параметры и значения по умолчанию
Чтобы сделать параметр необязательным, задайте ему значение по умолчанию через знак равенства. Если при вызове аргумент не передан, внутри функции параметр получит это значение.
Функция РассчитатьСуммуНДС(СуммаБезНДС, СтавкаНДС = 20)
Возврат СуммаБезНДС * СтавкаНДС / 100;
КонецФункции
// Оба вызова корректны:
НДС1 = РассчитатьСуммуНДС(100000); // ставка 20
НДС2 = РассчитатьСуммуНДС(100000, 10); // ставка 10
Необязательные параметры следует размещать в конце списка. Если необязательный параметр стоит перед обязательным, при вызове его нельзя просто пропустить — нужно явно поставить запятую, сохраняя позицию:
Функция СформироватьНадпись(Префикс = "№", Номер)
Возврат Префикс + " " + Номер;
КонецФункции
// Пропуск первого аргумента — пустая позиция между скобкой и запятой:
Надпись = СформироватьНадпись(, "123");
Проверить, передан ли аргумент в параметр без значения по умолчанию, можно сравнением с Неопределено. Это типичный приём для функций с гибким интерфейсом:
Если Отбор = Неопределено Тогда
Отбор = Новый Структура;
КонецЕсли;
Сравнение вариантов передачи
Подходит, когда функция должна изменить переданную переменную или когда передаётся большой объект и копирование нежелательно. Риск — случайное изменение данных вызывающего кода.
Подходит для входных данных, которые функция не должна менять. Для примитивных типов создаёт копию, для составных — копирует только ссылку.
Подходит, когда параметров больше трёх-четырёх: один параметр типа Структура с именованными полями вместо длинного списка позиционных аргументов.
Передача составных типов: структуры, массивы, таблицы значений
Когда функции нужно много связанных данных, удобнее передать одну структуру вместо длинного списка параметров. Такой вызов легче читать и расширять: добавление нового поля не ломает существующие вызовы.
Функция СоздатьДокументРеализации(ПараметрыДокумента)
Док = Документы.РеализацияТоваровУслуг.СоздатьДокумент();
Док.Дата = ПараметрыДокумента.Дата;
Док.Контрагент = ПараметрыДокумента.Контрагент;
Док.Организация = ПараметрыДокумента.Организация;
Док.Записать();
Возврат Док.Ссылка;
КонецФункции
// Вызов:
Параметры = Новый Структура;
Параметры.Вставить("Дата", ТекущаяДатаСеанса());
Параметры.Вставить("Контрагент", КонтрагентСсылка);
Параметры.Вставить("Организация", ОрганизацияСсылка);
НоваяСсылка = СоздатьДокументРеализации(Параметры);
Таблицы значений и массивы передаются так же, как любой другой параметр. Помните, что они передаются по ссылке: если функция добавляет строки в переданную таблицу, изменения видны в вызывающем коде. Если это нежелательно, внутри функции сделайте копию методом Скопировать() для таблицы значений.
Удобный шаблон — проверять наличие необязательных полей структуры методом Свойство(): Если Параметры.Свойство("Склад") Тогда ... Это позволяет вызывать функцию с разным набором полей и не получать ошибку обращения к несуществующему ключу.
Экспортные функции и вызов из других модулей
Функция, объявленная в модуле объекта, формы или общем модуле, по умолчанию доступна только внутри своего модуля. Чтобы вызвать её извне, после списка параметров добавьте ключевое слово «Экспорт»:
Функция ПолучитьЦенуНоменклатуры(Номенклатура, ДатаЦены = Неопределено) Экспорт
Если ДатаЦены = Неопределено Тогда
ДатаЦены = ТекущаяДатаСеанса();
КонецЕсли;
// ... получение цены из регистра
Возврат Цена;
КонецФункции
Вызов экспортной функции общего модуля выполняется через имя модуля: Цена = РаботаСЦенами.ПолучитьЦенуНоменклатуры(Товар);. Для этого общий модуль должен быть доступен в текущем контексте — например, серверный модуль нельзя вызвать напрямую с клиента без флага «Вызов сервера».
Проверка входных параметров и защита от ошибок
Надёжная функция проверяет входные данные до начала работы, особенно если она экспортная и вызывается из разных мест конфигурации. Минимальный набор проверок — на Неопределено, пустые ссылки и соответствие типа.
Функция ПолучитьОстаток(Номенклатура, Склад) Экспорт
Если Не ЗначениеЗаполнено(Номенклатура) Тогда
ВызватьИсключение "Не указана номенклатура";
КонецЕсли;
Если ТипЗнч(Склад) <> Тип("СправочникСсылка.Склады") Тогда
ВызватьИсключение "Параметр Склад имеет неверный тип";
КонецЕсли;
// ... основной код
КонецФункции
Функции ЗначениеЗаполнено() и ТипЗнч() покрывают большинство ситуаций. Явное исключение с понятным текстом экономит часы отладки: вместо падения глубоко внутри запроса вы сразу видите, какой параметр и почему не прошёл проверку.
Как проверить результат
Параметры в окне "Локальные переменные" содержат ожидаемые значения и типы
Параметр равен Неопределено или имеет неожиданный тип — ищите ошибку в вызове
После вызова переменные вызывающего кода не изменились (если не планировалось)
Исходная переменная изменилась — параметр передан по ссылке без «Знач»
Функция всегда доходит до оператора Возврат на любой ветке
На части веток Возврат отсутствует — результат Неопределено
Типичные ошибки при передаче параметров
Большинство проблем с параметрами сводится к нескольким повторяющимся сценариям. Знание их заранее сокращает время диагностики до минут.
Практические рекомендации по оформлению интерфейса функций
Держите число параметров в разумных пределах. Если их больше трёх-четырёх, объедините связанные данные в структуру — такой интерфейс проще читать, а вызовы не сломаются при добавлении нового поля. Имена параметров должны отражать смысл: ДатаНачала и ДатаОкончания вместо Д1 и Д2.
Документируйте функцию комментарием перед объявлением: назначение, описание каждого параметра с типом и возвращаемое значение. В конфигураторах с поддержкой расширенной подсказки такой комментарий отображается при наведении на вызов.
// Рассчитывает сумму НДС для указанной базы.
//
// Параметры:
// СуммаБезНДС - Число - база для расчёта.
// СтавкаНДС - Число - ставка в процентах, по умолчанию 20.
//
// Возвращаемое значение:
// Число - сумма налога.
//
Функция РассчитатьСуммуНДС(СуммаБезНДС, СтавкаНДС = 20) Экспорт
Возврат СуммаБезНДС * СтавкаНДС / 100;
КонецФункции
Что важно запомнить
Параметры объявляются в скобках и передаются позиционно. Без «Знач» параметр передаётся по ссылке и может быть изменён функцией; «Знач» защищает примитивные типы, но не содержимое структур и таблиц. Необязательные параметры задавайте через значения по умолчанию в конце списка, экспортные функции помечайте словом «Экспорт» и проверяйте входные данные в начале тела функции.
Частые вопросы
Чем функция отличается от процедуры по передаче параметров?
Синтаксис передачи параметров идентичен: те же «Знач», значения по умолчанию и «Экспорт». Разница только в результате: функция обязана вернуть значение оператором «Возврат», а процедура возвращает управление без значения. Если результат вычисления нужен вызывающему коду — используйте функцию.
Как передать в функцию произвольное число параметров?
Встроенного механизма переменного числа аргументов в языке 1С нет. Стандартный приём — передать массив или структуру: функция перебирает элементы коллекции и обрабатывает столько значений, сколько передано. Дополнительно можно объявить несколько необязательных параметров со значением Неопределено и проверять, какие из них заполнены.
Почему изменения структуры внутри функции видны снаружи, хотя стоит «Знач»?
Ключевое слово «Знач» копирует саму ссылку на объект, но не его содержимое. Структура, массив, таблица значений — ссылочные типы, поэтому и функция, и вызывающий код работают с одним экземпляром в памяти. Чтобы изолировать данные, создайте внутри функции копию: для таблицы значений — методом Скопировать(), для структуры — собрав новую структуру с теми же полями.
Можно ли передать в функцию другую функцию как параметр?
Напрямую передавать метод как значение нельзя. Обходные варианты: передать строку с именем метода и вызвать его через Выполнить() (с осторожностью, это исполнение произвольного кода) или использовать механизм описаний оповещений (ОписаниеОповещения) для асинхронных сценариев на клиенте.
Как вернуть из функции несколько значений?
Функция возвращает одно значение, но оно может быть составным: упакуйте результаты в структуру и верните её. Альтернатива — параметры, переданные по ссылке без «Знач»: функция записывает в них результаты, а вызывающий код читает их после вызова. Первый способ предпочтительнее, так как интерфейс остаётся явным.
Что произойдёт, если не передать обязательный параметр?
Конфигуратор при проверке модуля выдаст ошибку «Несоответствие количества параметров», и код не сохранится. Если же параметр объявлен без значения по умолчанию, но вызов прошёл (например, через Выполнить), внутри функции параметр будет равен Неопределено — поэтому проверка входных данных в начале тела функции остаётся полезной практикой.