Странное поведение аргументов холодного синтеза, выживших вне функции?

Я программировал ColdFusion более 15 лет, но никогда не сталкивался с этим. Вот код для репликации поведения:

<cfset _run()>
<cffunction name="_run">
  <cfset variables.dataArray=ArrayNew(1)>
  <cfset local.data={
    area="profile"
  }>
  <cfset _append(data=local.data,field="name")>
  <cfset _append(data=local.data,field="phone")>
  <cfdump var="#variables.dataArray#" label="dataArray">
</cffunction>
<cffunction name="_append">
  <cfargument name="data" type="struct" required="yes">
  <cfargument name="field" type="string" required="yes">
  <cfdump var="#arguments#" label="arguments">
  <cfset arguments.data.field=arguments.field>
  <cfset ArrayAppend(variables.dataArray,arguments.data)>
</cffunction>

Как вы можете видеть, это то, что я делаю:

  1. Включение массива в область видимости переменных, чтобы сделать его глобально доступным
  2. Инициирование структуры (local.data) в локальной области
  3. Добавление первого элемента поля (имени) путем вызова данных в функцию _append
  4. Присоединение второго элемента поля (телефона) таким же образом

Этот код приведет к следующему выводу:

Дамп вывода

Как видите, код приводит к массиву с повторяющимися записями, когда вы могли ожидать, что первый индекс должен иметь field="name". Как вы также можете видеть, значение данных, которое вызывается для _append во второй раз, содержит свойство "field" со значением "name". Кажется, что в области аргументов с первого раза мы вызвали функцию? Как это возможно. Я думал, что область аргументов была изолирована внутри тега cffunction?

Но если я заменю функцию _append этим:

<cffunction name="_append">
  <cfargument name="data" type="struct" required="yes">
  <cfargument name="field" type="string" required="yes">
  <cfdump var="#arguments#" label="arguments">
  <cfset local.data=Duplicate(arguments.data)>
  <cfset local.data.field=arguments.field>
  <cfset ArrayAppend(variables.dataArray,local.data)>
</cffunction>

это даст следующий вывод:

Дамп выхода 2

Как видите, создание дубликата arguments.data перед добавлением к нему "поля" решает проблему. Обратите внимание, что просто делать:

<cfset local.data=arguments.data>

было недостаточно.

Может кто-нибудь объяснить такое поведение аргументов области?

1 ответ

Поэтому после некоторого исследования я нашел это на странице документации Adobe Coldfusion (выделение текста выделено мной):

О масштабах аргументов

Все аргументы функции существуют в своей области видимости, области аргументов. Область действия Arguments существует в течение жизни вызова функции. Когда функция возвращается, область видимости и ее переменные уничтожаются. Однако уничтожение области действия Argument не приводит к уничтожению переменных, таких как структуры или объекты запросов, которые ColdFusion передает функции по ссылке. Переменные на странице вызова, которые вы используете в качестве аргументов функции, продолжают существовать; если функция изменяет значение аргумента, переменная на вызывающей странице отражает измененное значение.

Это открыло мне глаза, и в будущем это избавит меня от неприятностей:)

Другие вопросы по тегам