• 第十二章 变量作用域及内存


      JavaScript的变量与其它语言的变量有很大的区别。JavaScript变量是松散型(不强制类型)本质,决定了它只是在特定的时间用保存特定值的一个名字而已。由于不存在定义某个变量必须要保存何种数据类型值的规则,变量的值及其数据类型可以在脚本的生命周期内改变。

    一、变量及作用域

      1、基本类型和引用类型
      ECMAScript变量可以包含两种不同的数据类型的值:基本类型值和引用类型值。基本类型值指的是那些保存在栈内存中的简单数据段,即这种值完全保存在内存中的一个位置。而引用类型值则是指那些保存在堆内存中的对象,意思是变量中保存的实际上只是一个指针,这个指针指向内存中的另外一个位置,该位置保存对象。

      将一个值赋给变量时,解析器必须确定这个值是基本类型值,还是引用类型值;基本类型值有:Undefined,Null,Boolean,Number,String。这些类型在内存中分别占有固定大小的空间,他们的值保存在栈空间,我们通过按值来访问的。

      如果赋值是引用类型的值,则必须在堆内存中为这个值分配空间。由于这种值的大小不固定,因此不能把它们保存在栈内存中。但内存地址大小固定的,因此可以将内存地址大小保存在栈内存中。这样当查询引用类型变量时,先从栈中读取内存地址,然后通过地址找到堆中的值。

          

      2、动态属性

      定义基本类型值和引用类型值的方法是相似的:创建一个变量并为该变量赋值。但是,当这个值保存在变量中以后,对不同类型的值可以执行的操作则大相径庭。

      var pesson=new Object();      //创建引用类型

      pesson.name="boke";        //新增一个属性

      alert(pesson.name);         //输出

      如果基本类型值添加属性:

      var pesson="boke";         //创建一个基本类型

      pesson.age=29;           //给基本类型添加属性

      alert(pesson.age);          //undefined

      3、复制变量值

      在变量复制方面,基本类型和引用类型也有所不同。基本类型复制的是值的本身,而引用类型赋值的是地址。

      var box="Lee";           //在栈内存中生成一个box "Lee";

      var box2=box;          //在栈内存再生成一个box2 "Lee";

        

      box2虽然是box的一个副本,但从图可以看出,它们是独立的。也就是说,两个变量分别操作互不影响。

      var box=new Object();      //创建一个引用类型

      box.name="Lee"; 

      var box2=box;

       

      在引用类型中,box2其实就是box,因为他们指向的是一个对象。如果这个对象name属性的值修改,则另外一个也会被修改。

      4、传递参数

      ECMAScript中所有函数的参数都是按值传递的。

      function addTen(num){

        num += 10;

        return num;

      }

      var count = 20;

      var result = addTen(count);

      alert(count);              //20 没有变化

      alert(result);              //30

      传递的参数是一个基本类型,而函数里面的num是一个局部变量,和外面的的count没有任何关系。

      下面一个引用类型的例子。

      function setName(obj){

        obj.name="bo";

      }

      var persson = new Object();

      setName(persson);

      alert(persson.name);      //bo

      如果按引用传递的话,那么函数里面的那个变量将会是全局变量,在外部也可以访问。

      5、检测类型

      要检测一个变量的类型,我们可以用过typeof运算符来判别:

      var name = "类型";

      alert(typeof name);        //string

      虽然typeof运算符在检查基本的类型的时候非常好用。但检测引用类型的时候,它就不是那么好用。通常,我们并不向知道它是不是对象,而想知道它是什么类型的对象。因为数组也是object,null也是object类型等等;

      这时我们要采用instanceof运算符来查看。

      var num = [1,2,3];

      alert(num instanceof Array);          //true 是否是数组

      var num2={};

      alert(num2 instanceof Object);         //true 是否是对象

      var num3=/g/;

      alert(num3 instanceof RegExp);        //true 是否是正则表达式

      var num4=new String("Lee");

      alert(num4 instanceof String);         //true 是否是字符串

      当instanceof 检测基本类型的值,会返回false;

      5、执行环境及作用域

      执行环境是javascript中最重要的一个概念。执行环境定义了变量或函数有权访问的其它数据,决定了他们各自的行为。

      全局执行环境是最外围的执行环境。在WEB浏览器中,全局执行环境被认为是window对象。因此所有全局变量和函数都作为window对象的属性和方法创建的。

      var num = 123;            //声明一个全局的变量

      function sum(){

        alert(num);            //全局变量可以在函数内部访问 

      }

      function sum2(){

        alert(window.num);        //全局变量即window属性

      }

      sum();                //调用函数

      window.sum2();           //全局函数即window函数

      当执行环境中的所有代码执行完毕后,该环境被销毁,保存在其中的所有变量和函数定义也随之销毁。如果在全局环境下,需要程序执行完毕,或则网页关闭才销毁。

      每个执行环境都有一个与之关联的变量对象,就好比全局的window可以调用变量和属性一样。局部的环境也是一个类似window的变量对象,环境中定义的所有变量和函数都保存在这个对象中。

      var num = 100;

      function setNum(){

        var num = 200;

        alert(num);

      } 

      setNum();      //200

      alert(num);     //100

      6、没有块级作用域

      块级作用域表示诸如if语句等有花括号封闭的代码块,所以,支持条件判断定义变量。

      if(true){

        var num = 100;

      } 

      在if语句中定义的变量num,在if语句执行完毕后被销毁。

      

    内存问题

      JavaScript具有自动垃圾收集机制,也就是说,执行环境会负责管理代码执行过程中使用的内存。其他语言比如C和C++,必须手工跟踪内存使用情况,适时的释放,否则会造成很多问题。而JavaScript则不需要这样,它会自行管理内存分配及无用内存的回收。

      JavaScript最常用的垃圾收集方式是标记清除。垃圾收集器会在运行的时候给存储在内存中的变量加上标记。然后,它会去掉环境中正在使用变量的标记,而没有被去掉标记的变量将被视为准备删除的变量。最后,垃圾收集器完成内存清理工作,销毁那些带标记的值并回收他们所占用的内存空间。

      垃圾收集器是周期性运行的,这样会导致整个程序的性能问题。比如IE7以前的版本,它的垃圾收集器是根据内存分配量运行的,比如256个变量就开始运行垃圾收集器,这样,就不得不频繁地运行,从而降低的性能。

      一般来说,确保占用最少的内存可以让页面获得更好的性能。那么优化内存的最佳方案,就是一旦数据不再有用,那么将其设置为null来释放引用,这个做法叫做解除引用。这一做法适用于大多数全局变量和全局对象。

      var obj = {

        num = 100;

      };

      obj = null;          //解除对象引用,等待垃圾收集器回收 

      

  • 相关阅读:
    大文件上传
    http协议
    memcache通过hash取模算法,实现多服务器存取值
    页面静态化案例---一键生成详情页面静态化(全站静态化+局部动态)
    页面静态化案例---一键生成详情页面静态化(全站静态化)
    页面静态化案例---数据列表静态化
    LCD1602液晶显示模块的单片机驱动深入详解之硬件篇
    ANDROID开发之GC_CONCURRENT freed
    ANDROID开发之OOM:一张图片(BitMap)占用内存的计算 图片内存优化
    ANDROID开发 Fatal signal 11(SIGSEGV) at 0x问题解决方案
  • 原文地址:https://www.cnblogs.com/xchit/p/JavaScript_12.html
Copyright © 2020-2023  润新知