2013-02-21 112 views
18

我有一個在全局範圍內的函數之外定義的對象。該對象不作爲參數傳遞給函數,但該函數會修改它並返回修改後的對象。JavaScript函數默認情況下是否通過引用或值返回對象?

我想知道的是,如果函數返回對象的副本或原始全局對象?

此外,將該對象作爲參數傳遞給函數,有所作爲,因爲通過引用將對象傳遞給函數?

+0

只有明確地這樣做,纔不會複製對象。 – 2013-02-21 15:43:33

+6

而不是說「對象通過引用傳遞給函數」,更準確地說,對象的*引用*是按值傳遞的。看到這裏:http://stackoverflow.com/questions/518000/is-javascript-a-pass-by-reference-or-pass-by-value-language/5314911#5314911 – 2013-02-21 15:46:06

回答

42

每當你返回一個對象,你返回對象的引用。同樣,當你傳遞一個對象時,你傳遞了一個引用。但是,將參數作爲參數傳遞給可能與僅改變全局範圍內的對象不同,如這些示例所示。這是因爲對象的引用本身是按值傳遞的。

如果您要更改對象的成員,那麼無論您是將其作爲參數傳遞還是更新全局對象都沒有區別。無論哪種方式,你正在使用同一個對象。

例1:

var object = {foo:'original'}; 

function changeObject() { 
    object.foo = 'changed'; 
    return object; 
} 

console.log(changeObject()); // outputs {foo:'changed'} 
console.log(object); // outputs {foo:'changed'} 

例2:

var object = {foo:'original'}; 

function changeArgument(object) { 
    object.foo = 'changed'; 
    return object; 
} 

console.log(changeArgument(object)); // outputs {foo:'changed'} 
console.log(object); // outputs {foo:'changed'} 

在另一方面,如果你覆蓋了新對象的對象,該變化不會,如果你堅持這樣做它的參數,但如果你對全局對象做這件事,它將會持續下去。這是因爲參數按值傳遞了對象的引用。一旦你用一個新對象的引用替換這個值,你就不再談論同一個對象了。

例3:

var object = {foo:'original'}; 

function replaceObject() { 
    object = {foo:'changed'}; 
    return object; 
} 

console.log(replaceObject()); // outputs {foo:'changed'} 
console.log(object); // outputs {foo:'changed'} 

例4:

var object = {foo:'original'}; 

function replaceArgument(object) { 
    object = {foo:'changed'}; 
    return object; 
} 

console.log(replaceArgument(object)); // outputs {foo:'changed'} 
console.log(object); // outputs {foo:'original'} 
+0

當然,如果你希望'replaceArgument(object)'和'replaceObject'具有相同的最終結果,你可以'object = replaceArgument(object)' – 2013-02-21 16:06:05

+6

這是一個很好的答案。 – rgthree 2013-02-21 17:09:45

1

我想知道的是,如果函數返回對象的副本或原始全局對象?

實際上,您只處理JavaScript中對象的引用。即使var foo = {}只是將對新的對象的引用分配給foo

1

如果對象在函數之外,則不需要「返回」它。如果修改函數內的對象,它將更新對象本身。然後,您可以根據需要在其他函數中引用新更新的對象。

+1

這是有道理的。但是,就我而言,返回它有助於將單個對象從巨大的集合中分離出來,這樣我就不需要再次查找該對象。 – 2013-02-21 15:52:18

+0

嗯。不知道我理解你的情況。你能發佈一個代碼示例嗎? – LoneWolfPR 2013-02-21 16:00:52

1

從你的問題,這是我怎麼想你的代碼看起來(或多或少):

var o = {}; 

function f() { 
    o.prop = true; 
    return o; 
} 
  1. 在這種情況下,全局變量o引用的對象。
  2. 當您修改o時,您將修改任何o引用。因此它修改了原始對象。
  3. 當您返回o時,您將返回對原始對象的引用。

將對象傳遞給函數會導致對傳遞的原始對象的引用。因此任何修改都會影響原始對象。例如:

var o = {}; 

f(o); 

console.log(o.prop); // true 

function f(o) { 
    o.prop = true; 
} 
0

可能會遲到評論,但是這是在任何語言的典型挑戰。 Obects在堆上創建,並通過引用與基元(按值)相對傳遞。 我認爲問題的根源是共享實例與獨特實例,以避免不受歡迎的影響。 例如我們調用一個函數來獲取新用戶添加到集合的模板(對象),或者想要清除不同模塊的取消事件的表格 以重新開始。這很容易理解和容易overlook..test案件通常 沒有覆蓋所有使用排列

理智清單: 這裏共享實例:

var bigo = { 

    usr: {name: 'steven'}, 
    bigi: function() { 
     return this.usr; 
    } 
}; 
var outA = bigo.bigi(); 

var outB = bigo.bigi(); 

print(outA.name); 

print(outB.name); 

outA.name = 'ilan'; // change value 

print(outA.name); 

print(outB.name); 

以上的農產品:

steven 

steven 

ilan 

ilan 

非共享:

var bigo = { 

    bigi: function() { 
     var user = {name: 'steven'}; 
     return user; 
    } 
}; 

var outA = bigo.bigi(); 

var outB = bigo.bigi(); 


print(outA.name); 

print(outB.name); 

outA.name = 'ilan'; // change value 

print(outA.name); 

print(outB.name); 

o輸出:

steven 

steven 

ilan 

steven 
相關問題