2013-09-30 82 views
1

我試過下面的代碼,但它提醒舊的對象名稱屬性?我知道對象是通過引用傳遞的,但是通過引用傳遞,那麼在函數內部改變的對象也應該在函數外面改變,不是嗎?是否通過引用或值傳遞JavaScript對象

function setName(obj) { 
obj.name = "raziq"; 
obj = new Object(); 
obj.name = "abdul"; 
} 
var person = new Object(); 
setName(person); 
alert(person.name); //still yields raziq 

我有點糊塗了,如果對象是通過引用傳遞,則新的名稱應警惕爲什麼它仍然戒備阿卜德拉爲對象的名稱?

+0

你爲什麼要創建的setName內的新對象? –

+0

@ThomasWood爲了說明問題 – Phil

+0

以查看它是否將person對象更改爲函數外部,因爲如果通過引用傳遞對象,則函數內部的新對象應該反映在函數isn'之外,它呢? –

回答

2

當您將new Object()分配給變量obj時,實際上並沒有交換原始對象。計算機爲您剛剛實例化的對象創建了一個新的內存點,併爲名稱屬性賦值「abdul」,但不會更改上一個對象,因爲它駐留在內存中的不同位置。新創建的對象從不離開函數。

而不是將obj變量視爲容納該對象的容器,可以將其視爲佔位符的數字地址的佔位符。當您將person傳入該函數時,您傳遞的是該地址,而不是該對象本身。因此,在函數內部,當您創建新對象時,您將該新對象的地址存儲在佔位符obj中。函數外部的變量person仍然包含原始對象的地址,而不是您在函數中創建的新地址。

+0

是不是通過引用傳遞的對象? –

+4

@abdul:不。傳遞的*值*是對象的引用,但不稱爲「通過引用傳遞」。這仍然是「傳遞價值」。請參閱https://en.wikipedia.org/wiki/Pass_by_reference#Call_by_reference。 –

+1

是的,但該函數正在使用ADDRESS的副本來引用該對象。當你改變函數中的變量時,你正在改變地址。 – THEtheChad

2

在JavaScript中沒有「通過引用」。你可以傳遞一個對象(,也就是說,你可以傳值一個對象的引用),然後有一個函數修改對象的內容。

Source for reference

在JavaScript中,我們擁有的功能,我們有我們傳遞到這些函數的參數。但是,JavaScript如何處理你傳遞的內容並不總是很清楚。當你開始進行面向對象的開發時,你可能會發現自己爲什麼有時可以訪問值而不是其他時候感到困惑。

當傳入像字符串或數字這樣的基本類型變量時,該值將按值傳入。這意味着在函數中對該變量的任何更改都與函數外部發生的任何變化完全分離。讓我們來看看下面的例子:

function myfunction(x) 
{ 
     // x is equal to 4 
     x = 5; 
     // x is now equal to 5 
} 

var x = 4; 
alert(x); // x is equal to 4 
myfunction(x); 
alert(x); // x is still equal to 4 

然而,傳入一個對象,通過引用傳遞它。在這種情況下,該對象的任何屬性都可以在該函數內訪問。讓我們來看另一個例子:

function myobject() 
{ 
    this.value = 5; 
} 
var o = new myobject(); 
alert(o.value); // o.value = 5 
function objectchanger(fnc) 
{ 
    fnc.value = 6; 
} 
objectchanger(o); 
alert(o.value); // o.value is now equal to 6 

所以,當你傳遞一個對象的方法時會發生什麼?大多數人會期望(或至少我做過),它會通過引用傳遞,允許方法訪問它分開的對象的其他部分。不幸的是,情況並非如此。看看這個例子:

function myobject() 
{ 
    this.value = 5; 
} 
myobject.prototype.add = function() 
{ 
    this.value++; 
} 
var o = new myobject(); 
alert(o.value); // o.value = 5 
o.add(); 
alert(o.value); // o.value = 6 
function objectchanger(fnc) 
{ 
    fnc(); // runs the function being passed in 
} 
objectchanger(o.add); 
alert(o.value); // sorry, still just 6 

這裏的問題是使用'this'關鍵字。這是指當前對象上下文的簡便方法。但是,當將函數作爲參數傳遞時,上下文將丟失。更準確地說,它現在指的是調用對象的上下文,而不是我們剛剛傳入的對象的函數。對於獨立函數,這將是窗口對象,對於從事件調用的函數,這將是事件對象。

+1

*「傳入一個對象,然而,通過引用傳遞它。」*不! JavaScript總是**通過價值傳遞。只是在發生對象的情況下,纔會傳遞對該對象的引用。但是,這不是通過引用。按引用傳遞將是'var foo = 42; (function(baz){baz = baz/2}(foo));警報(FOO);/*會提醒21 * /',但這不是JS的工作方式。 –

+0

我看到了圖片 –

+0

@FelixKling:這也不完全是通過價值。真正按值傳遞(就像在諸​​如tcl之類的語言中一樣)會複製整個對象。我更願意稱之爲「通過參考副本傳遞」,這就是你所說的。當你認爲javascript總是傳遞一個引用的副本(或者,在你的術語中,引用的值)時,它總是表現相同 - 即使對於數字和字符串也是如此。 – slebetman

3

在您的代碼:

> function setName(obj) { 

在調用的第一個參數的值分配給本地變量OBJ。如果一個對象被傳遞,obj的值是對該對象的引用。

> obj.name = "raziq"; 

這將分配值「阿卜德拉」傳遞給OBJ對象的財產。如果名稱屬性不存在,則會創建該屬性。

> obj = new Object(); 

此分配一個新對象的引用作爲OBJ值,所以它不再引用傳遞給函數的對象。

> obj.name = "abdul"; 

該值「阿卜杜勒」分配給名稱屬性(創建如果它不存在它的屬性)由OBJ(創建並分配在線之上的新引用的對象的)。

由於沒有其他參考這個對象,它只要在函數結束可供垃圾收集。

> } 
> 
> var person = new Object(); 

創建一個新對象,並將其分配給變量的值是對新對象的引用。

> setName(person); 

呼叫的setName並將其傳遞上面的行創建的對象。功能分配阿卜德拉到對象的名稱屬性(見上文)。

> alert(person.name); //still yields raziq 

警報上面創建並分配給對象的名稱屬性的值。由於raziq被分配爲值,這就是返回的內容。

需要注意的是一個新的對象是在函數創建並賦值語句創建屬性,但對象不是任何地方分配或從函數返回,所以一切後:

obj = new Object(); 

無效。

請注意,這是比較常見的寫:

obj = {}; 

具有完全相同的結果作爲前行,但少打字和更廣泛的使用,因此有可能(略)更容易閱讀和維護。

+0

很好的解釋 –

相關問題