К статье
Практический материал

Разработка и Конфигурация · 12 мин

Как передать значение в функцию 1С

Как передать значение в функцию 1С: объявление параметров, передача по значению и по ссылке, ключевое слово Знач, параметры по умолчанию и типичные ошибки с примерами кода.

Передача значения в функцию в 1С выполняется через параметры, которые перечисляются в круглых скобках при объявлении функции и при её вызове. Встроенный язык 1С поддерживает передачу по значению и по ссылке, параметры со значениями по умолчанию и пропуск необязательных аргументов. Понимание этих механизмов нужно и при написании собственных процедур, и при вызове методов типовых конфигураций.

Основная сложность для начинающих разработчиков — поведение параметров-ссылок: функция может изменить переданный объект, и это изменение отразится на вызывающем коде. Обратная ситуация — когда разработчик ожидает изменения, но использует ключевое слово Знач, которое создаёт копию значения. Ниже разобраны оба сценария с примерами кода и способами проверки результата.

Материал ориентирован на встроенный язык 1С:Предприятие 8.3. Синтаксис одинаково работает в общих модулях, модулях объектов, форм и внешних обработок.

Как объявить функцию с параметрами

Функция объявляется ключевым словом Функция, после имени в круглых скобках перечисляются параметры через запятую. Тип параметра не указывается — язык 1С динамически типизирован, поэтому в один и тот же параметр можно передать число, строку, ссылку на объект или структуру.

Функция РассчитатьСуммуСНДС(Сумма, СтавкаНДС)

Результат = Сумма + Сумма * СтавкаНДС / 100;

Возврат Результат;

КонецФункции

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

Итого = РассчитатьСуммуСНДС(10000, 20);

Сообщить(Итого); // 12000

Порядок аргументов при вызове строго позиционный: первый аргумент попадёт в первый параметр, второй — во второй. Именованный вызов в стиле «параметр = значение» на уровне вызова в 1С не поддерживается, поэтому при большом числе параметров принято передавать структуру.

Передача по ссылке и по значению: ключевое слово Знач

По умолчанию параметр передаётся по ссылке: если внутри функции присвоить параметру новое значение, изменится и переменная в вызывающем коде. Это удобно, когда функция должна вернуть больше одного результата, но часто становится источником скрытых ошибок.

Функция Удвоить(Число)

Число = Число * 2;

Возврат Число;

КонецФункции

А = 5;

Б = Удвоить(А);

// Теперь А = 10, Б = 10 — переменная А изменилась!

Ключевое слово Знач перед именем параметра меняет поведение: в функцию передаётся копия значения, и исходная переменная защищена от изменений.

Функция УдвоитьБезопасно(Знач Число)

Число = Число * 2;

Возврат Число;

КонецФункции

А = 5;

Б = УдвоитьБезопасно(А);

// А = 5, Б = 10 — исходная переменная не изменилась

Сравнение способов передачи

По ссылке (по умолчанию)

Функция может изменить переданную переменную. Подходит, когда нужно вернуть несколько результатов через параметры. Риск — непреднамеренное изменение данных вызывающего кода.

Знач (по значению)

Передаётся копия, исходная переменная защищена. Подходит для большинства функций. Ограничение — дополнительные затраты на копирование больших таблиц значений.

Структура с параметрами

Один параметр-структура вместо множества аргументов. Подходит при числе параметров больше трёх-четырёх и для расширяемых программных интерфейсов.

Особенность объектных типов

Для объектов изменяемых типов — массивов, структур, таблиц значений, списков значений — передаётся ссылка на сам объект. Даже с ключевым словом Знач копируется ссылка, а не содержимое: функция по-прежнему может добавить строку в переданную таблицу значений, и это увидит вызывающий код. Знач защищает только от переприсваивания самой переменной.

Параметры по умолчанию и пропуск аргументов

Если параметр не обязателен, ему задаётся значение по умолчанию через знак равенства в объявлении. Такие параметры должны стоять в конце списка — после них нельзя объявлять обязательные.

Функция НайтиТовары(Номенклатура, ТолькоВНаличии = Истина, Склад = Неопределено)

// Если вызывающий код не передал Склад, внутри будет Неопределено

...

КонецФункции

При вызове необязательные аргументы можно опустить полностью, если они идут в конце, либо пропустить запятой, если нужно задать более поздний параметр:

Результат1 = НайтиТовары(Товар);                    // оба параметра по умолчанию

Результат2 = НайтиТовары(Товар, Ложь); // задан второй

Результат3 = НайтиТовары(Товар, , СкладОсновной); // второй пропущен, задан третий

Пропущенный через запятую параметр получает значение по умолчанию, а если оно не задано — Неопределено. Внутри функции полезно проверять такие параметры через ЗначениеЗаполнено() или сравнение с Неопределено, прежде чем использовать их в запросах и сравнениях.

Передача нескольких значений через структуру

Когда параметров больше трёх-четырёх, позиционный вызов становится хрупким: добавление нового параметра в середину списка сломает все существующие вызовы. Практическое решение — передать одну структуру, где каждое значение имеет имя.

Функция СформироватьЗаказ(ПараметрыЗаказа)

Организация = ПараметрыЗаказа.Организация;

Контрагент = ПараметрыЗаказа.Контрагент;

// ...

КонецФункции

Параметры = Новый Структура;

Параметры.Вставить("Организация", МояОрганизация);

Параметры.Вставить("Контрагент", МойКонтрагент);

Параметры.Вставить("Комментарий", "Срочно");

Результат = СформироватьЗаказ(Параметры);

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

Как передать значение в функцию общего модуля и на сервер

Функции, размещённые в общих модулях, вызываются через имя модуля: Результат = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(Ссылка, "Наименование");. Чтобы функция была видна извне, в объявлении указывается ключевое слово Экспорт после списка параметров.

Функция ПолучитьКурс(Валюта, Дата) Экспорт

// ...

КонецФункции

При вызове серверной функции из клиентского кода (модуль с флагами «Сервер» и «Вызов сервера») действует ограничение: параметры и возвращаемое значение должны быть сериализуемыми, то есть передаваемыми между клиентом и сервером. Ссылки, примитивные типы, структуры, массивы и таблицы значений передаются свободно, а объекты типа ДокументОбъект, Запрос или COMОбъект — нет. Попытка передать такой объект вызовет ошибку передачи данных между клиентом и сервером.

Типичные ошибки
01
Передача ДокументОбъекта с клиента на сервер — возникает ошибка сериализации. Передавайте ссылку, а объект получайте на сервере через Ссылка.ПолучитьОбъект().
02
Изменение параметра внутри функции без Знач — вызывающий код неожиданно получает изменённую переменную, что приводит к ошибкам в расчётах.
03
Вызов функции как процедуры без использования результата — компилятор 1С выдаёт ошибку, функцию нельзя вызвать отдельным оператором без присваивания.
04
Несовпадение порядка аргументов при вызове — данные попадают не в те параметры, ошибка проявляется только в логике, а не на этапе компиляции.
05
Обязательный параметр после необязательного в объявлении — синтаксическая ошибка, все параметры со значениями по умолчанию должны идти в конце списка.

Проверка типа и значения входных параметров

Поскольку тип параметра не фиксируется в объявлении, защитные проверки выполняются в начале тела функции. Это особенно важно для экспортируемых функций общих модулей, которые вызываются из разных мест конфигурации.

Функция РассчитатьСкидку(Сумма, ПроцентСкидки) Экспорт

Если ТипЗнч(Сумма) <> Тип("Число") Тогда

ВызватьИсключение "Параметр Сумма должен быть числом";

КонецЕсли;

Если Сумма < 0 Тогда

ВызватьИсключение "Сумма не может быть отрицательной";

КонецЕсли;

Возврат Сумма * ПроцентСкидки / 100;

КонецФункции

Проверка типа выполняется функцией ТипЗнч() в сочетании с Тип(). Для ссылочных типов удобно проверять на пустую ссылку через ЗначениеЗаполнено(). Если параметр некорректен, осмысленное исключение через ВызватьИсключение лучше молчаливого возврата Неопределено — ошибка будет обнаружена сразу, а не в дальнейших вычислениях.

Контрольные точки

Как проверить результат

Поведение параметра после вызова
Норма

Переменная вызывающего кода не изменилась, если этого не требовалось

Тревожный признак

Переменная изменилась — параметр передан по ссылке без Знач

Значение необязательного параметра
Норма

При пропуске аргумента внутри функции значение по умолчанию или Неопределено

Тревожный признак

Ожидалось конкретное значение, но оно не задано в объявлении

Вызов серверной функции с клиента
Норма

Код выполняется без ошибок передачи данных

Тревожный признак

Ошибка о невозможности передачи значения — передан несериализуемый тип

Синтаксис-проверка модуля
Норма

Конфигуратор не выдаёт ошибок при проверке модуля

Тревожный признак

Ошибка о несоответствии числа параметров или порядке необязательных

Как вернуть несколько значений из функции

Оператор Возврат возвращает одно значение. Когда результатов несколько, применяются три подхода: вернуть структуру с именованными полями, вернуть массив с позиционными элементами или передать изменяемые параметры по ссылке. Первый вариант — самый читаемый и безопасный.

Функция РазобратьСтрокуАдреса(СтрокаАдреса) Экспорт

Результат = Новый Структура;

Результат.Вставить("Город", "");

Результат.Вставить("Улица", "");

Результат.Вставить("Индекс", "");

// ... заполнение полей

Возврат Результат;

КонецФункции

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

Итог

Что важно запомнить

Параметры передаются в функцию 1С позиционно через скобки. По умолчанию — по ссылке, ключевое слово Знач защищает от изменения переменной. Необязательные параметры объявляются со значением по умолчанию в конце списка. Для множества параметров используйте структуру, для клиент-серверных вызовов — только сериализуемые типы. Проверяйте типы входных данных в начале тела функции.

Частые вопросы о передаче значений в функции 1С

Чем функция отличается от процедуры при передаче параметров?

Механизм передачи параметров идентичен: те же правила про Знач, значения по умолчанию и передачу по ссылке. Разница только в результате: функция возвращает значение через Возврат и обязана использоваться в выражении, а процедура вызывается отдельным оператором и ничего не возвращает.

Можно ли передать в функцию другое функцию или метод?

Напрямую указателей на функции во встроенном языке нет. Обходные решения: передать имя метода строкой и вызвать через Выполнить() (небезопасно и медленно) или использовать механизм оповещений ОписаниеОповещения для асинхронных сценариев, где метод обратного вызова указывается по имени экспортной процедуры.

Почему изменения массива внутри функции видны снаружи, хотя указано Знач?

Знач копирует ссылку на массив, но не его содержимое: и вызывающий код, и функция работают с одним и тем же массивом в памяти. Чтобы получить независимую копию, внутри функции создайте новый массив и скопируйте элементы, либо для коллекций с методом Скопировать() используйте его.

Как передать параметры в функцию фонового задания?

Метод ФоновыеЗадания.Выполнить() принимает массив параметров вторым аргументом: ФоновыеЗадания.Выполнить("МойМодуль.МояПроцедура", МассивПараметров). Элементы массива распределяются по параметрам процедуры по порядку. Все значения должны быть сериализуемыми, так как сохраняются в очереди заданий.

Что произойдёт, если передать аргументов меньше, чем объявлено параметров?

Если недостающие параметры объявлены со значениями по умолчанию — они получат эти значения. Если обязательные — компилятор выдаст ошибку «Несоответствие числа переданных параметров» ещё на этапе синтаксической проверки модуля, до выполнения кода.

Как передать таблицу значений с клиента на сервер?

Таблица значений сериализуется, поэтому передаётся в серверную функцию напрямую как обычный параметр. Исключение — таблица, связанная с элементом формы (данные формы): её сначала преобразуют через РеквизитФормыВЗначение(), передают, а на клиенте возвращают обратно через ЗначениеВРеквизитФормы().