2014-07-02 115 views
0

我今天又在閱讀我的javascript書籍,它解釋了引用類型變量和基元類型變量之間的區別。它給出了這些例子來說明不同之處。字符串:JavaScript中的原始類型變量或引用類型變量?

實施例1(原語類型)

var a = 3.14; 
var b = a; 
a = 4; 
alert(b); // Displays 3.14 

實施例2(參考類型)

var a = [1, 2, 3]; 
var b = a; 
var a[0] = 99; 
alert(b); // Displays the changed array [99, 2, 3] 

我理解這個例子,我沒有關於它的任何問題。我的問題是關於JavaScript中的字符串。直覺上,我會假定字符串是引用類型變量,因爲如果動態大小,但我在example.com上搞亂了它們,並且我創建了這個似乎表明字符串是原始類型變量的示例。

例3(字符串?)

var a = 'Ben'; 
var b = a; 
var a = 'Benjamin'; 
alert(b); //Displays the unchanged 'Ben' 

我搜索在這裏對堆棧溢出,並在谷歌,我發現,談到這一點,但他們大多都在談論其他語言的幾篇文章如Java和C#。

問: 在javascript中的字符串認爲是原始的或引用變量的類型以及是否有我應該知道的地方串不同的工作,那麼我會想到的任何其他情況呢?

+0

如果您嘗試使用數組'['B','e','n']'的示例3,則您將獲得相同的結果 - 將新值(另一個數組)分配給'a'變量這不會影響'b'。嘗試使用示例2(其中您更改'a'的'0'字段)使用字符串 - 它會引發異常。 – Bergi

回答

2

在JavaScript中,字符串是不可變的,因此是原始類型。

他們有不同的大小就像不同數量的數字。它們的大小不是動態,您不能更改現有字符串值的大小。每當你做字符串操作時,你都在創建新的值。就像var x = 1; x += 2將不會更改1值(但創建一個新的3值),var var a = "Hi!"; a += "!"將不會更改字符串"Hi!"

+0

'var a =「Hi!」; a + =「!」;'你可以將字符添加到一個字符串中,以便它們的大小可以改變,但是你不能這麼做,比如'a [2] =「?」'。 –

+0

雖然這很可能受JS引擎中實現選擇的影響,但字符串可能通過引用傳遞(例如,當傳遞給相同字符串的其他用戶時不會創建副本),但是由於它們是不可變的,並且給定的字符串永遠不會被改變,他們最終表現得更像原始人。 – jfriend00

+2

@NobleMushtak - 那真的不對。當你「改變」一個字符串時,它會產生一個新的字符串。原始字符串從未改變。試試這個:'var a =「嗨!」; var b = a; a + =「!」;'。現在看看'b'和'a'。它們是不同的,告訴你a中的字符串沒有真正改變,但是一個新的字符串是隨着它的改變而創建的。 – jfriend00

2

當您做a = 'Benjamin'時,賦值運算符(=)更改a指向的對象。它不會改變其他變量指向的對象。舉例說明:

var a, b; 

a = "Ben";  // `a` now points to "Ben" in memory 
b = a;   // `b` now points to "Ben" in memory 
a = "Benjamin"; // `a` now points to "Benjamin" in memory, but 
       // `b` still points to "Ben" 

這對字符串沒有什麼特別之處;任何基元或對象值的語義都是相同的。

正如Bergi所指出的那樣,您的問題的答案的一個重要部分是JavaScript中的字符串是不可變的,所以無論它們的實現如何,它們本質上都是作爲原語行事的。同樣,說明:

a = "Ben"; // `a` now points to "Ben" in memory 
b = a;  // `b` now points to "Ben" in memory 
a += "jamin"; // `a` now points to "Benjamin" in memory, but 
       // `b` still points to "Ben" 

a += "jamin",正如你所知道的是相當於a = a + "jamin",不改變字符串ab點;它將創建一個新的字符串,其值爲"Benjamin",並使a指向它而不是"Ben"。 ("Ben""Benjamin"是否在內存中共享任何相同字節是對JavaScript程序完全不透明的實現細節。)

+0

問題的關鍵在於「本」(在'a')和'「本」(在'b')是否在內存中共享字節......重點在於它們不是從JavaScript的角度來看的,它甚至不知道「內存」中的「字節序列對象」。 – Bergi

+0

@Bergi我想你和我只是說了同樣的事情。 –

+0

啊,對,我剛剛提到'b = a;'賦值後的狀態。沒有真正理解'jamin''增加了什麼解釋... – Bergi

0

在JavaScript中,字符串是基元。

儘管如此,還是應該加以改進的。纏繞物體。如字符串,數字,布爾原語得到的物體包裹起來,這樣你就可以在這些包裝對象調用屬性,insance:

var foo = 'bar'; 
var poo = foo.slice(0,-1) 
poo == 'ar'; //true 

這裏字符串「酒吧」在有切片方法對象(和許多包裹起來其他的),但在其他所有情況下(當你只是傳遞原始變量等等)時,變量只是一個原語。

+0

包裝對象僅用於查找屬性(引擎將優化掉)的「創建」,您無法觀察它(除非在馬虎模式中) – Bergi

+0

你是什麼意思,'觀察'呢? –

+1

你不能記錄它,顯示它,使用它......它所做的只是它提供了一個屬性,你永遠不會看到實際的包裝器對象(在你的例子中)。沒有理由意識到任何事情。 – Bergi

0

如約旦所說,如果您更改實際對象的值而不僅僅是屬性,則示例3不起作用,即使對象是JavaScript中的引用類型,對象指向的對象也不會更改。

然而,字符串是不可變的和原始值,所以即使我們做了這樣的事情:

var a = "Hi!"; 
var b = a; 
a[2] = "?"; 
alert(a); 
alert(b); 

a仍然是"Hi!"因爲字符串是不可改變的,b仍然是"Hi!"即使a"Hi?"因爲字符串是原始值。