2017-12-15 103 views
5

Tôi đã lập trình ColdFusion trong hơn 15 năm, nhưng chưa bao giờ bắt gặp điều này. Dưới đây là một mã số để nhân rộng các hành vi:Hành vi lạ thường của các đối số coldfusion tồn tại bên ngoài chức năng?

<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> 

Như bạn có thể thấy điều này là những gì tôi làm:

  1. Initing một mảng trong phạm vi biến để làm cho nó trên toàn cầu thể truy cập
  2. Initing một struct (local.data) trong phạm vi địa phương
  3. Gắn thêm mục trường đầu tiên (tên) bằng cách gọi dữ liệu đến hàm _append
  4. Gắn thêm mục trường thứ hai (điện thoại) vào thứ e cùng cách

Mã này sẽ cho kết quả đầu ra sau đây:

Dump of output

Như bạn thấy, kết quả mã trong một mảng với mục trùng lặp, khi bạn có thể mong đợi rằng các chỉ số đầu tiên nên có field = "name". Như bạn cũng có thể thấy, giá trị của dữ liệu được gọi để _append lần thứ hai, chứa thuộc tính "trường" với giá trị "name". Dường như nó nằm trong phạm vi đối số từ lần đầu tiên chúng ta gọi hàm này? Sao có thể như thế được. Tôi nghĩ rằng phạm vi đối số được phân lập bên trong thẻ cffunction?

Nhưng nếu tôi thay thế các chức năng _append với điều này:

<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> 

nó sẽ cho kết quả như sau:

Dump of output 2

Như bạn thấy, làm cho một bản sao của arguments.data trước khi thêm "trường" vào nó, giải quyết vấn đề. Lưu ý rằng chỉ cần thực hiện:

<cfset local.data=arguments.data> 

là không đủ.

Ai đó có thể giải thích hành vi này của phạm vi đối số?

Trả lời

4

Vì vậy, sau khi một số nghiên cứu, tôi thấy điều này trên Adobe Coldfusion Documentation Page (bolding văn bản được thực hiện bởi tôi):

Về phạm vi Arguments

Tất cả các đối số chức năng tồn tại trong phạm vi riêng của họ, Phạm vi đối số. Phạm vi đối số tồn tại trong suốt cuộc gọi hàm. Khi hàm trả về, phạm vi và các biến của nó bị hủy. Tuy nhiên, phá hủy phạm vi Đối số không phá hủy các biến, chẳng hạn như cấu trúc hoặc đối tượng truy vấn, ColdFusion chuyển đến hàm bằng tham chiếu. Các biến trên trang gọi mà bạn sử dụng làm đối số hàm vẫn tiếp tục tồn tại; nếu hàm thay đổi giá trị đối số, biến trong trang gọi phản ánh giá trị đã thay đổi.

Đây là một cái mở mắt cho tôi, và nó sẽ giữ cho tôi ra khỏi rắc rối trong tương lai :)

+0

Yeah, đối tượng phức tạp nhất được thông qua tham khảo. Mảng là một ngoại lệ lạ. Hầu hết thời gian chúng được chuyển "theo giá trị". Vì vậy, một udf như _append không thể sửa đổi trạng thái của mảng bên ngoài hàm đó. – Ageax

+0

Bạn có thể sử dụng ArrayList của Java ('createObject (" java, "java.util.ArrayList"). Init() ') nếu bạn cần một mảng bằng tham chiếu. – Alex

Các vấn đề liên quan