zoukankan      html  css  js  c++  java
  • 变量、作用域和内存问题

    一、基本类型和引用类型的值

    1、ECMAscript变量包含两种数据类型的值:基本类型值和引用类型值。

    1)基本类型值:undefined、null、boolean、string和number

    存储方式:在内存中占据大小固定的空间,被保存在栈内存中。

    2)引用类型值:保存在内存中的对象

    存储方式:堆内存

    2、如何检测变量类型

    1)typeof

    传统的检验工具,但,typeof对于基本数据类型值中的undefined、boolean、string和number有效,但在检验null和对象时无效,检验结果二者均为object。

    2)instanceof

    判断一个对象是什么类型的对象,如果变量是给定引用类型的实例,instanceof操作符就会返回true。

    语法如下:

    result=rariable instanceof constructor

    注意:instanceof不能用来检测基本数据类型,该操作符始终会返回false,因为基本数据类型根本不是对象

    3)、传递参数

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

    易错点

    •  向参数传递引用类型值时,会将这个值在内存中的地址复制给一个局部变量(参数实际上是这个函数的局部变量)。因此这个局部变量的变化会反映在函数的外部。

    •  错误观点:在局部作用域中修改的对象会在全局作用域中反映出来,就说明参数是按引用传递的。证明如下

    1 function setName(obj){
    2    obj.name='xiaohuyang';
    3    obj=new object();
    4    obj.name='laohuyang';
    5 }
    6 var person=new object();
    7 setName(person);
    8 alert(person.name);//xiaohuyang

    如果参数是按引用传递的,在函数内修改参数的值时,原始引用应同时变化,而事实并没有。事实上,当在函数内部重写obj时,这个变量引用的就是一个局部对象了,而这个局部对象在函数执行完毕后立即被销毁。(可以被ECMAscript函数的参数想象成局部变量~~~)

    二、执行环境及作用域

    这一块需要特别记得不多,主要是延长作用域链这一块。虽然执行环境的类型总共只有两种,全局和局部(函数),但还是有其他办法来延长作用域链的,这么说是因为有些语句可以在作用域的前端临时增加一个变量对象,该变量对象会在代码执行后被移除。在以下两种语句中会发生延长作用域链的情况。具体来说,是当执行流进入下列任何一个语句时,作用域链就会得到延长。

    1、try-catch中的catch语句

    对于catch语句来说,会创建一个新的变量对象,其中包含的是被抛出的错误对象的声明,而这个变量对象会被添加到作用域链的前端。(说实话这个我不会用哦,等我会用了再来补充~~~)

    2、with语句

    function buildUrl(){
      var qs='12345';
      with(location){
      var url=href+qs;
      }
      return url;
    }

     with语句接受的location对象,其变量对象中就包含了location对象的所有属性和方法,而这个变量对象被添加到了作用域的前端。

     注意:js没有块级作用域哦。

    三、垃圾收集

    1、标记清除和引用计数

    js具有自动垃圾收集机制,也就说执行环境会负责管理代码执行过程中使用的内存,其原理:找出不再继续使用的变量,然后释放其占用的内存。为此,垃圾收集器会按照固定的时间间隔周期性的执行这一操作。

    那么,垃圾收集器如何判断垃圾变量是否还有存在的必要呢?垃圾收集器会跟踪变量,然后对不再有用的变量打上标记,以便将来收集回收的其占用的内存,用于标识无用变量的策略,具体到浏览器的实现,一般分为两种:

    1)、标记清除——最常用(IE、Firefox、Opera、Chrome、Safari等)

    当变量进入环境时,就把这个变量标记为“进入环境”,永远不能释放有进入环境标记变量的内存,因为只要执行流进入相应的环境,就可能会用到它们。而当变量离开环境时,则将其标记为”离开环境“。垃圾收集器在运行过程中会给存储在内存中的所有变量都加上标记,然后它会去掉环境中的变量及被环境中的变量引用的变量。而在此之后再被加上标记的变量将被视为准备删除的变量,原因是,环境中的变量已经无法访问到这些变量了。最后,垃圾清理器完成内存清理工作,销毁带标记的值,并回收他们所占用的内存空间。

    注意:不同浏览器使用的垃圾回收的时间间隔互有不同。

    2)、引用计数——不太常见

    引用计数,即跟踪记录每个值被引用的次数,声明了一个变量并将一个引用类型值赋给该变量时,则这个值得引用次数就是1(eg,var object1=new object()),如果同一个值每被引用一次,该值得引用标记就加1,包含对这个值引用的变量若取得其他值,该值标记就减一,当该值的引用标记为0时说明无法访问该值了,就可以将其占用的内存空间回收回来。最后,垃圾收集器定时清理。

    注意:引用计数策略在遇到循环引用情况,会出现很大问题

    2、性能问题

    这一点不是很懂~~~

    3、管理内存

    由于分配给web浏览器的可用内存数量通常要比分配给桌面应用程序的少(出于安全方面考虑,防止运行js的网页耗尽全部系统内存而导致系统崩溃),这一内存限制问题 不仅会影响给变量分配内存,还会影响调用栈以及在 一个线程中能够同时执行的语句数量。

    因此,确保占用最少的内存可以让页面获得更好的性能。而优化内存的最佳方式,就是为执行中的代码只保存必要的数据。一旦数据不再有用,最好将其设置为null来释放其引用——即,解除引用。这一做法适应大多数全局变量和全局对象的属性。局部变量会在他们执行环境时自动解除引用,其他的则需手动解除引用。

    1 function createPerson(name){
    2         var localPerson=new Object();
    3         localPerson.name=name;
    4         return localPerson;
    5     }
    6 var globalPerson=createPerson("xiaohuyang");
    7 //下面必须手动解除localPerson的引用。
    8 localPerson=null;
  • 相关阅读:
    Matlab命令集常用字符串函数
    统计独立性和统计相关性
    查看solaris下硬盘的物理大小
    Perl命令行开关
    DateFormat.getDateInstance出现Unparseable date
    ActiveMQ 本地转本地再转远程的完整配置
    aspose.words 操作word生成试卷
    汇编in和out介绍
    eclipse开发国际化项目利器:MultiProperties
    RCP+GEF+界面开发(2)[eclipse插件配置LINK方法]
  • 原文地址:https://www.cnblogs.com/MelodysBlog/p/10448913.html
Copyright © 2011-2022 走看看