在 http://www.blogjava.net/magicdoom/archive/2006/02/27/32555.html中 有言:
“在JavaScript中,String也传引用的.”
让我们来看下面这个例子:
function
setName(obj)
{
obj
=
"
minchanghe
"
;
}
var
name
=
"
hechangmin
"
;
setName(name);
alert(name);
//
hechangmin
发现输出的 name并没有发生变化,所以这地方还是值得我们进一步研究。
在上文 http://www.blogjava.net/JAVA-HE/archive/2010/03/18/315798.html 有讲过,对于传入的引用参数,如果重新赋值,将自动生成 拷贝,而不影响原来引用。
这时候我琢磨下面这个例子也许能通过引用参数来完成修改效果:
String.prototype.ok
=
"
aaaaa
"
;
function
setName(obj)
{
obj.ok
=
"
ccccccc
"
;
}
var
name
=
"
hechangmin
"
;
alert(name.ok);
//
aaaaa
setName(name);
alert(name.ok);
//
aaaaa
不幸的是,上例还是失败告终。这到底是什么呢?稍安勿躁,我的答案总会给出,即使不完全正确。
我们再来看下面这个例子:
var
test
=
new
String(
"
minchanghe
"
);
var
name
=
"
minchanghe
"
;
alert(test
==
name);
//
true => 值相等
alert(test
===
name);
//
false => 类型不同
//
验证下
alert(
typeof
test );
//
object
alert(
typeof
name );
//
string
我们很容易就得到了一个结论,通过new String 产生的字符串对象 和 以字符串常量产生的字符串对象他们是有区别的,即使他们有相同的值。
这时候也许你思考传引用还有戏,因为我们还没有试过 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
这个结果不错吧。 的确实现了前后两次输出内容的变化。说明以 new String() ,你直接看成普通的object对象即可理解。 (前面用typeof验证过这个也的确是 object )
本来文章写到这里想结束了,结果发现前面留下的那个问题,并没有解决。这时候我们不难找到资料来说明 new String 和 直接用字符串常量产生的字符串对象的区别在哪里?
在
《JavaScript 语言参考》中文版.chm 手册上看到如下的说明:
String 对象可用字符串文字显式创建。用这种方法创建的 String 对象(指以标准字符串形式)与用
new
运算符创建的 String 对象处理上不同。所有字符串文字共享公用的全局字符串对象。如果为字符串文字添加属性,则它对所有标准字符串对象都是可用的:
var
alpha, beta;
alpha
=
"
这是一个字符串
"
;
beta
=
"
这也是一个字符串
"
;
alpha.test
=
10
;
在前一示例中,这时为 beta 和所有将来的字符串定义 test。然而,在下面的例子中,被添加属性的处理略有不同:
var
gamma, delta;
gamma
=
new
String(
"
这是一个字符串
"
);
delta
=
new
String(
"
这是也一个字符串
"
);
gamma.test
=
10
;
在这种情况下,不为 delta 定义 test。每个用
new
String 声明的 String 对象有其自己的一组成员。这是对 String 对象和字符串文字的处理不同的唯一情况。
尽信书不如无书,我随手试了下其中的代码:
var
alpha, beta;
alpha
=
"
这是一个字符串
"
;
beta
=
"
这也是一个字符串
"
;
alpha.test
=
10
;
alert(beta.test);
//
undefined
靠,这手册也太不经不起验证了吧。。。那上面那个问题怎么办?
一个办法:如果以字符串常量产生的字符串对象以传值来看待。
想起曾经的一个bug,这里提一点:
1.toString 函数返回string
2.var x = String("a"); 生成string
3.new String() 创建object
有一次以json跟C++ GUI 通信过程 ,我居然 new String()了,这个bug很低级,但是却让我找得比较辛苦。
我又想起一篇介绍 javascript内存泄露的文章,如果有兴趣可以访问:
http://www.blogjava.net/JAVA-HE/archive/2009/10/27/299856.html
其中有讲:
自动类型装箱转换:这种泄露存在于ie6 ie7中。这是极其匪夷所思的一个bug,看下面代码
var
s
=
"
lalalalala
"
;alert(s.length);
这段代码怎么了?看看吧,
"
lalalalala
"
已经泄露了。关键问题出在s.length上,我们知道js的类型中,string并非对象,但可以对它使用.运算符,为什么呢?因为js的默认类型转换机制,允许js在遇到.运算符时自动将string转换为object型中对应的String对象。而这个转换成的临时对象100
%
会泄露(汗一下)。
当然看到这里我有疑惑,前面的示例我有:alert(name.ok);
那是否就应该说这里有自动装箱机制编程 object呢? 如果变成object后,那地方的传引用实验能成功才对啊?
哈哈,中计了,其实装箱那地方产生的只是临时对象。