2014-07-02 86 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?"因为字符串是原始值。