“在JavaScript中,String也傳引用的.”
讓我們來(lái)看下面這個(gè)例子:
function setName(obj)
{
obj = "minchanghe";
}
var name = " hechangmin ";
setName(name);
alert(name); // hechangmin
{
obj = "minchanghe";
}
var name = " hechangmin ";
setName(name);
alert(name); // hechangmin
發(fā)現(xiàn)輸出的 name并沒(méi)有發(fā)生變化,所以這地方還是值得我們進(jìn)一步研究。
在上文 http://www.aygfsteel.com/JAVA-HE/archive/2010/03/18/315798.html 有講過(guò),對(duì)于傳入的引用參數(shù),如果重新賦值,將自動(dòng)生成 拷貝,而不影響原來(lái)引用。
這時(shí)候我琢磨下面這個(gè)例子也許能通過(guò)引用參數(shù)來(lái)完成修改效果:
String.prototype.ok = "aaaaa";
function setName(obj)
{
obj.ok = "ccccccc";
}
var name = " hechangmin ";
alert(name.ok); // aaaaa
setName(name);
alert(name.ok); // aaaaa
function setName(obj)
{
obj.ok = "ccccccc";
}
var name = " hechangmin ";
alert(name.ok); // aaaaa
setName(name);
alert(name.ok); // aaaaa
不幸的是,上例還是失敗告終。這到底是什么呢?稍安勿躁,我的答案總會(huì)給出,即使不完全正確。

我們?cè)賮?lái)看下面這個(gè)例子:
var test = new String("minchanghe");
var name = "minchanghe";
alert(test == name); // true => 值相等
alert(test === name); // false => 類型不同
// 驗(yàn)證下
alert(typeof test ); // object
alert(typeof name ); // string
var name = "minchanghe";
alert(test == name); // true => 值相等
alert(test === name); // false => 類型不同
// 驗(yàn)證下
alert(typeof test ); // object
alert(typeof name ); // string
我們很容易就得到了一個(gè)結(jié)論,通過(guò)new String 產(chǎn)生的字符串對(duì)象 和 以字符串常量產(chǎn)生的字符串對(duì)象他們是有區(qū)別的,即使他們有相同的值。
這時(shí)候也許你思考傳引用還有戲,因?yàn)槲覀冞€沒(méi)有試過(guò) new String。 好,看下面的例子:
function setName(obj)
{
obj.ok = "ccccccc";
}
var name = new String("hechangmin");
String.prototype.ok = "aaaaa";
alert(name.ok); // aaaaa
setName(name);
alert(name.ok); // ccccccc
{
obj.ok = "ccccccc";
}
var name = new String("hechangmin");
String.prototype.ok = "aaaaa";
alert(name.ok); // aaaaa
setName(name);
alert(name.ok); // ccccccc
這個(gè)結(jié)果不錯(cuò)吧。 的確實(shí)現(xiàn)了前后兩次輸出內(nèi)容的變化。說(shuō)明以 new String() ,你直接看成普通的object對(duì)象即可理解。 (前面用typeof驗(yàn)證過(guò)這個(gè)也的確是 object )
本來(lái)文章寫到這里想結(jié)束了,結(jié)果發(fā)現(xiàn)前面留下的那個(gè)問(wèn)題,并沒(méi)有解決。這時(shí)候我們不難找到資料來(lái)說(shuō)明 new String 和 直接用字符串常量產(chǎn)生的字符串對(duì)象的區(qū)別在哪里?
在 《JavaScript 語(yǔ)言參考》中文版.chm 手冊(cè)上看到如下的說(shuō)明:
String 對(duì)象可用字符串文字顯式創(chuàng)建。用這種方法創(chuàng)建的 String 對(duì)象(指以標(biāo)準(zhǔn)字符串形式)與用 new 運(yùn)算符創(chuàng)建的 String 對(duì)象處理上不同。所有字符串文字共享公用的全局字符串對(duì)象。如果為字符串文字添加屬性,則它對(duì)所有標(biāo)準(zhǔn)字符串對(duì)象都是可用的:
var alpha, beta;
alpha = "這是一個(gè)字符串";
beta = "這也是一個(gè)字符串";
alpha.test = 10;
在前一示例中,這時(shí)為 beta 和所有將來(lái)的字符串定義 test。然而,在下面的例子中,被添加屬性的處理略有不同:
var gamma, delta;
gamma = new String("這是一個(gè)字符串");
delta = new String("這是也一個(gè)字符串");
gamma.test = 10;
在這種情況下,不為 delta 定義 test。每個(gè)用 new String 聲明的 String 對(duì)象有其自己的一組成員。這是對(duì) String 對(duì)象和字符串文字的處理不同的唯一情況。
var alpha, beta;
alpha = "這是一個(gè)字符串";
beta = "這也是一個(gè)字符串";
alpha.test = 10;
在前一示例中,這時(shí)為 beta 和所有將來(lái)的字符串定義 test。然而,在下面的例子中,被添加屬性的處理略有不同:
var gamma, delta;
gamma = new String("這是一個(gè)字符串");
delta = new String("這是也一個(gè)字符串");
gamma.test = 10;
在這種情況下,不為 delta 定義 test。每個(gè)用 new String 聲明的 String 對(duì)象有其自己的一組成員。這是對(duì) String 對(duì)象和字符串文字的處理不同的唯一情況。
盡信書不如無(wú)書,我隨手試了下其中的代碼:
var alpha, beta;
alpha = "這是一個(gè)字符串";
beta = "這也是一個(gè)字符串";
alpha.test = 10;
alert(beta.test); //undefined
alpha = "這是一個(gè)字符串";
beta = "這也是一個(gè)字符串";
alpha.test = 10;
alert(beta.test); //undefined
靠,這手冊(cè)也太不經(jīng)不起驗(yàn)證了吧。。。那上面那個(gè)問(wèn)題怎么辦?
一個(gè)辦法:如果以字符串常量產(chǎn)生的字符串對(duì)象以傳值來(lái)看待。
想起曾經(jīng)的一個(gè)bug,這里提一點(diǎn):
1.toString 函數(shù)返回string
2.var x = String("a"); 生成string
3.new String() 創(chuàng)建object
有一次以json跟C++ GUI 通信過(guò)程 ,我居然 new String()了,這個(gè)bug很低級(jí),但是卻讓我找得比較辛苦。
我又想起一篇介紹 javascript內(nèi)存泄露的文章,如果有興趣可以訪問(wèn):
http://www.aygfsteel.com/JAVA-HE/archive/2009/10/27/299856.html
其中有講:
自動(dòng)類型裝箱轉(zhuǎn)換:這種泄露存在于ie6 ie7中。這是極其匪夷所思的一個(gè)bug,看下面代碼
var s="lalalalala";alert(s.length);
這段代碼怎么了?看看吧,"lalalalala"已經(jīng)泄露了。關(guān)鍵問(wèn)題出在s.length上,我們知道js的類型中,string并非對(duì)象,但可以對(duì)它使用.運(yùn)算符,為什么呢?因?yàn)閖s的默認(rèn)類型轉(zhuǎn)換機(jī)制,允許js在遇到.運(yùn)算符時(shí)自動(dòng)將string轉(zhuǎn)換為object型中對(duì)應(yīng)的String對(duì)象。而這個(gè)轉(zhuǎn)換成的臨時(shí)對(duì)象100%會(huì)泄露(汗一下)。
var s="lalalalala";alert(s.length);
這段代碼怎么了?看看吧,"lalalalala"已經(jīng)泄露了。關(guān)鍵問(wèn)題出在s.length上,我們知道js的類型中,string并非對(duì)象,但可以對(duì)它使用.運(yùn)算符,為什么呢?因?yàn)閖s的默認(rèn)類型轉(zhuǎn)換機(jī)制,允許js在遇到.運(yùn)算符時(shí)自動(dòng)將string轉(zhuǎn)換為object型中對(duì)應(yīng)的String對(duì)象。而這個(gè)轉(zhuǎn)換成的臨時(shí)對(duì)象100%會(huì)泄露(汗一下)。
當(dāng)然看到這里我有疑惑,前面的示例我有:alert(name.ok);
那是否就應(yīng)該說(shuō)這里有自動(dòng)裝箱機(jī)制編程 object呢? 如果變成object后,那地方的傳引用實(shí)驗(yàn)?zāi)艹晒Σ艑?duì)啊?
哈哈,中計(jì)了,其實(shí)裝箱那地方產(chǎn)生的只是臨時(shí)對(duì)象。