zoukankan      html  css  js  c++  java
  • JavaScript局部变量与全局变量1

    在一个函数中(或类定义中),有用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好象是全程有效。因此取名不要乱取,不要与其它全局变量重名了。

  • 相关阅读:
    linux uniq 命令实用手册
    linux sort 命令实用手册
    linux awk 命令实用手册
    如何高效使用vim
    15个有趣好玩的linux shell 命令
    一篇文章带你编写10种语言HelloWorld
    如何用hugo 搭建博客
    c++中的exit()
    枚举数据类型C++
    常见的字符测试函数
  • 原文地址:https://www.cnblogs.com/yzx99/p/1286265.html
Copyright © 2011-2022 走看看