Указатели компонентов Coldfusion - PullRequest
1 голос
/ 01 октября 2011

У меня проблема с компонентом Coldfusion, который я создаю. Ну, я не совсем уверен, если это проблема или как вещи должны работать, но это кажется странным. Сначала я устанавливаю аргументы для функции init моего компонента и вызываю компонент. Но если я изменю один из аргументов после вызова, он также изменит значения, содержащиеся в компоненте. Это правильно?

Я не уверен, объясняю ли я это очень хорошо. Вот некоторый псевдокод:

<cfset fruit = [] />
<cfset fruit[1] = {
    id = 1,
    name = "apple"
} />
<cfset fruit[2] = {
    id = 2,
    name = "orange"
} />

<cfset args = {
    title = "Fruit",
    data = fruit
} />

<cfinvoke component="test" method="init" returnvariable="test" argumentcollection=#args# />

<cfset fruit[2].name = "banana" />

Функция init сохраняет аргументы title и data в области действия variables компонента.

Теперь, если я выведу данные из объекта test, я получу apple и banana. Но я ожидал, что компонент сохранит данные, полученные во время вызова.

Дайте мне знать, если мне нужно что-то прояснить. Спасибо за любую помощь!

Ответы [ 2 ]

5 голосов
/ 01 октября 2011

Я не совсем уверен, если это проблема или как все должно работать,

Да, именно так должен работать ваш текущий код.Является ли это так, как вы хотите, чтобы он вел себя, - это другой вопрос.

Большинство сложных объектов (структур, компонентов, etectera) передаются по ссылке .Это означает, что вы по сути просто храните указатель на объект, а не на фактические значения.Таким образом, вы всегда будете видеть любые изменения, сделанные в базовом объекте.Вот почему выходные данные из test изменяются.

Массивы являются исключением.Они обычно (хотя и не всегда) передаются значением .Это означает, что у вас есть независимая копия, которая не будет отражать какие-либо изменения, внесенные в исходный объект.

Ваш пример интересен, потому что он содержит оба.Изменения ваших вложенных структур (name=orange => name=banana) видны в компоненте, поскольку структуры передаются по ссылке.Но родительского массива нет.Таким образом, вы можете очистить fruit, и это не повлияет на компонент.

Пример:

<cfset fruit[2].name = "bananna" />

<!--- both dumps will show "bananna" --->
<cfdump var="#fruit#" label="Fruit Before" />
<cfdump var="#test.getDataArray()#" label="Test.Data Before" />

<cfset arrayClear(fruit) />

<!--- fruit is empty and the component array is not --->
<cfdump var="#fruit#" label="Fruit After" /> 
<cfdump var="#test.getDataArray()#" label="Test.Data After" /> 

Тест:

<cfcomponent>

  <cffunction name="init" returntype="any" ...>
     <cfargument name="title" type="string" required="true" />
     <cfargument name="data" type="array" required="true" />
     <cfset variables.title = arguments.title />
     <cfset variables.data = arguments.data />
     <cfreturn this />   
  </cffunction>

  <cffunction name="getDataArray" returntype="array">
     <cfreturn variables.data />
  </cffunction>

</cfcomponent>

Теперь, если я выведу данныес тестового объекта я получаю яблоко и банан.

Верно.Этого следовало ожидать, потому что структуры передаются по ссылке.Если вы хотите, чтобы компонент содержал независимую копию, вам нужно duplicate() (т.е. глубокое копирование) элемента data внутри init().

   <cfset variables.data = duplicate(arguments.data) />
3 голосов
/ 01 октября 2011

В то время как массивы передаются в VALUE в ColdFusion, даже объекты внутри них. Если вы хотите сохранить значения в функции, верните массив, который обновляет ваша функция инициализации, и установите для него свой массив fruit.

Я бы получил функцию получения, которая вернула бы ваш массив:

<cffunction name="getArray" returntype="array" access="public" output="false" hint="return the array" >
    <cfreturn variables.theArray>
</cffunction>

И в вашем шаблоне cfm вы установите свой массив фруктов равным этому значению:

<cfset fruit = test.getArray()>
...