2011-10-21 52 views
1

我知道JavaScript總是通過引用傳遞對象。但其他類型呢?何時複製值?

number - ?
字符串 - 不可阻擋,所以它應該沒有關係
object-ref
array - ?
功能 - ?
regexp - ?

我得出的結論是在Javascript中並不是所有的值可以是對象,也不能被引用與傳遞following code

function SomeFunc(func) { 
    var numba = 0; 
    var innerFunc = function() { 
     numba = func(numba);//try commenting me out and switching to next line 
     //func(numba);//numba fails to increment 
     return numba; 
    }; 
    return innerFunc; 
} 

//this variable should persist the numba variable through closure. Incrementing each call by 1. 
var closure = SomeFunc(function(numba) { 
    numba = numba + 1; 
    return numba; 
}); 

document.writeln(closure()); 
document.writeln(closure()); 
document.writeln(closure()); 

因爲numba沒有增加,除非我返回的數量和更新封閉中的變量...然後,這告訴我這不是通過引用傳遞。我錯過了什麼嗎?


或採取非常基本

function UpdateNumber(numba) { 
    numba = 10; 
    document.writeln('in func number becomes ' + numba); 
} 

var numba2 = 5; 
UpdateNumber(numba2); 

document.writeln('back to caller number is ' + numba2); 
//in func number becomes 10 
//back to caller number is 5 
+0

我通過電子郵件發送Douglas Crockford和他對這種情況的迴應是:「當你賦值給一個變量時,你給變量一個引用,當你傳遞一個變量作爲參數時,變量本身。「我相信這個問題僅僅是我還有很多東西需要學習。 –

回答

4

號的JavaScript總是經過值,而不是通過引用。

人們經常會混淆修改方法中對象的能力,並將修改作爲傳遞引用在外部顯示。不是這種情況。通過引用傳遞意味着修改值指向的外部函數。例如

var f1 = function (p1) { 
    p1 = 42; 
}; 
var x = {}; 
f1(x); 

在這個例子中,如果實現的JavaScript通過引用傳遞然後x === 42將是真實的。但事實並非如此。變量x仍將具有值{}

+2

「通過引用傳遞對象,它們永遠不會被複制」 - 「Javascript:The Good Parts」Douglas Crockford –

+1

@ P.Brian.Mackey引用仍然被傳遞。 「按引用傳遞」和「按值傳遞引用」有所不同。 JavaScript做後者。 – JaredPar

+0

在JavaScript中,沒有指針,所以通過引用需要一種不同的含義... – xavierm02

1

每個對象都通過引用傳遞。事實上,一切都是一個對象。

function addProperty(o) { 
    o.property = 'value'; 
} 

// here, we can see that even numbers are passed by reference 
var n = new Number(1); 
addProperty(n); 
console.log(n.property);// 'value' 

但是,即使一切按引用傳遞,爲litterals,你可以認爲他們是按值傳遞,因爲你無法修改它們。

var n = 1; 
n.property = 'value'; 
console.log(n.property);// undefined 

在ES 5中,存在這種新函數Object.freeze,它使對象無法修改。 基本上,當你傳遞一個litteral時,你正在做的是傳遞一個不可變的對象。

var n = 1; 
var o = Object.create(null); 
Object.freeze(o); 
doWhatTheFuckYouWant(o); 
doWhatTheFuckYouWant(n); 

在這兩種情況下,你可以肯定的是,因爲沒有什麼可以改變關於對象的功能將沒有什麼改變你的對象。因此,你只是不在乎它是否被克隆。

2

我認爲這是更富有成效想想這樣的:

  • 有可變的(對象,數組等)和不可變的(數字,布爾值,字符串)值。
  • 參數傳遞總是通過賦值。
  • 在函數外部看不到參數的賦值,因爲您只是將局部變量改爲指向別的地方。
  • 如果對象是可變的,你調用方法或指定的屬性,這些變化被視爲功能

(即沒有副本已到,當它被傳遞給函數的對象進行)外所以你不需要知道類型是否通過引用傳遞,你需要檢查它是否可變。