yzx99

导航

 

在一个函数中(或类定义中),有用var定义的变量为局部变量,没有定义就赋值的是全局变量。没有定义就使用的,IE提示错误“'x'未定义”。
好象很简单,但自己实际去试一下才发现问题多多。

 

我写一个函数,然后在VS2005中调试,我就想看一看在开发环境如何看出是局部变量与全局变量。
function abc()
{
 var i=0;
 a=1;
 i=a;
}

abc();
var o1=abc;
alert(o1.i); //提示undefined
alert(a);    //提示1
debugger;    //快速监视this,但找不到a,只有监视this.a才出现
结果,虽然a是正确地提示出来,但我无法在快速监视this中看到a,只有快速监视this.a才能看到。这里的this为window。VS2008会如何?(后面,在调试中的局部窗口中可以看到this的东西

 

如果用类的方式来写:
var abc=function()
{
 var i;

 a=1;   //相当于构造函数
 i=a;
}

var o1=new abc();
alert(o1.i);
alert(a);
debugger;
得到的结果是一样的,我都监视不到明显的类的属性。


对比我的函数写法,以及别人的类写法,发现一个学习点:
var o1=abc;        //让o1等于abc,因此其它地方可以执行o1();也就是执行abc();,

typeof(o1)="function"
var o1=abc();      //执行abc,并把返回值给o1,typeof(o1)="undefined"
var o1=new abc();  //o1为类abc的实例,该代码也会执行函数abc,不过这美其名曰“构
造函数”,typeof(o1)="object"
对比一下,发现还是“外国的月亮圆”,别人的代码强!

 

再对比一下,还有function的写法不一样,下面的写法被称为匿名函数,上面的写法则是普通写法,但据说上面写的同时,javaScript也生成了一个同名对象。
我再找,总算在VS2005中找到了它,以及前面提到的私有变量与全局变量。在“调试”菜单的“窗口”子菜单的“局部变量”中可以看到对应的局部变量。
有了这个窗口,我现在应该敢怀疑这句话“上面写的同时,javaScript也生成了一个同名对象”,或者我理解错了作者原意。反正,系统里面只有一个该名字的对象,其typeof的值为function,而不是该名字的对象有两个,一个object,一个function。

 

function比string这些简单类型更牛的是:function可以这样
abc.i=2;
而string这些简单类型就不能这样了:
var s="OK";
s.i=9;  //这样也不行:s.prototype.i=9;

 

存取全局变量速度比局部变量要慢得多
用以下网页来验证
<html>
<head>
<script>

var a = new Date();
a1();
document.write((new Date() - a) + ":");

a = new Date();
a2();
document.write((new Date() - a) + "  ");

a = new Date();
a3();
document.write((new Date() - a) + ":");

a = new Date();
a4();
document.write((new Date() - a) + "  ");

//设置全局变量
function a1()
{
 var i;
 for (i=0; i<100000; i++)
 {
  b=1;
 }
}

//设置局部变量
function a2()
{
 var i;
 var b;
 for (i=0; i<100000; i++)
 {
  b=1;
 }
}

//读取全局变量
function a3()
{
 var i;
 c=2;
 var b;
 for (i=0; i<100000; i++)
 {
  b=c;
 }
}

//读取局部变量
function a4()
{
 var i;
 var c=2;
 var b;
 for (i=0; i<100000; i++)
 {
  b=c;
 }
}

</script>
</head>
<body>
</body>
</html>
执行结果为:109:78 94:62 不是固定这个值,但能说明全局变量比局部变量慢30-40%。看来“存取全局变量速度比局部变量要慢得多”这句话没错!

 

如果要频繁使用全局变量,可以设定一个局部变量,先把全局变量拷贝过来再使用。
这句会不会又有什么问题?
如果是向上面的测试代码,拷贝过来应该是没有问题的。但如果全局变量是在变化之中的话,拷贝过来会跟着变化吗?
以下代码做这个测试:
<html>
<head>
<script>

function a1()
{
 var i;
 a=2;
 var b;
 b=a;

 a=3;
 alert(b);  //显示2

 b=4;
 alert(a);  //显示3
}

function a2()
{
 var i;
 a=new Object();
 var b;
 b=a;

 a.i=5;
 alert(b.i);  //显示5

 b.i=6;
 alert(a.i);  //显示6
}

function a3()
{
 var i;
 a=new Object();
 var b;
 b=a;

 a.i=5;
 alert(b.i);  //显示5

 a=new Object();
 a.i=6;
 alert(b.i);  //显示5
}

a1();
a2();

</script>
</head>
<body>
</body>
</html>
测试时发现,如果a是简单类型,b=a也只是值的拷贝,因此如果全局变量变化了,不会反映到局部变量。如果a是对象类型,b=a就是地址的拷贝,因此如果全局变量下面的属性变化了,可以反映到局部变量中。但如果是a变成新的对象时,b的引用又不对了。
因此可以说,要想用拷贝全局变量来加快速度,程序员要考虑在使用过程中是否值有没有被更改,或对象有没有新建过。

 

VS进入到with时,会有什么反应
<html>
<body>
<script>
 var i=12;
 var a=new Object();
 a.i=5;
 a.j=6;
 with (a)
 {
  temp=i;
  i=j;
  j=temp;
 }
 alert(i);
</script>
</body>
</html>
从代码中要记住with的格式,后面带一个圆括号,中间为想节省的对象,后面再带一个代码块。中间如果有使用对象的属性,就自动引用,而使用非对象的属性,则当做外面的普通变量处理。
进入with后,VS好象没有什么变化,至少“局部变量”窗口没有什么变化。但提示功能中对i的提示,就自动使用a.i的值了。出来后,又继续提示全局变量i的值了。
这里看,用于with确实可能造成一定的混乱,难怪JsLint不建议使用。

 

我现在编写javascript还没到会用try...catch的地步,先小试一个:
<html>
<body>
<script>
{
 var a=b;
}
catch(e)
{
 alert("       e.name:" + e.name + "\n" +
       "    e.message:" + e.message + "\n" +
       "     e.number:" + e.number.toString(16) + "\n" +
       "e.description:" + e.description);
 a=1;
}
finally
{
 alert(a);
}
</script>
</body>
</html>
有点像VB中的on error goto xxx。如果按照我的编程原则,对已知的错误,要想办法避免,对未知的错误,应该要提示出来,并且程序停止(就是使用系统自带的功能),这样用户才会有向你报怨。对无法避免的已知错误,才需要使用on error goto xxx。我在JavaScript中太多未知的错误,因此至今还没有哪个需要用到try来防止错误重复发生。
这里会提到try...catch是因为变量e只是在catch作用区内才有效,但我测试时,却发现事实却非如此。e好象是全程有效。因此取名不要乱取,不要与其它全局变量重名了。

posted on 2008-09-07 16:41  yzx99  阅读(2954)  评论(0编辑  收藏  举报