变量、作用域和内存问题

ECMAScript包含两种不同数据类型的值:基本类型值和引用类型值。基本类型值指的是简单的数据段,引用类型值指的是可能由多个值构成的对象。
    |--我们能给引用类型动态地添加属性,但是无法给基本类型添加属性。
    |--复制变量的值时,基本类型得到了一个新值,引用类型。

参数传递:

    |--基本类型值作为参数被传递给函数时,会将值复制给函数中的一个局部变量。因此,局部变量改变不会影响原来的基本类型值。而引用类型值传递的是对象的引用,都指向同一个对象,如果将局部引用指向新的对象,原引用仍指向原来的对象

检测类型:
    |--typeof方法检测基本类型是一把好手,但是通常我们并不是想知道某个值是对象,而是想知道是什么类型的对象,为此,ECMAScript提供了instanceof操作符:
result = variable instanceof constructor
注意:因为所有的引用类型的值都是Object的实例,所以result的值始终为true,如果用instanceof检查基本类型,则始终返回false,因为基本类型不是对象。

执行环境及作用域
    |--执行环境(execution context) 是JavaScript中最为重要的一个概念。执行环境定义了变量或函数有权访问其他数据,决定了它们各自的行为。每个环境都有一个与之关联的变量对象(variable object),环境中定义的所有变量和函数都保存在这个对象中。
    全局执行环境是最外围的一个执行环境。根据ECMAScript实现所在的宿主环境不同,表示执行环境的对象也不一样。如在web浏览器中,全局执行环境被认为是window对象,因此所有全局变量和函数都是作为window对象的属性和方法创建的。某个执行环境中的所有代码执行完毕后,该环境被销毁,保存在其中的所有变量和函数定义随之销毁(全局执行环境直到应用程序退出时才会被销毁)。
    每个函数都有自己的执行环境。当执行流进入一个函数时,函数的环境就会被推入一个环境栈中。而在函数执行之后,栈将其环境弹出,把控制权返回给之前的执行环境。
    当代码在一个环境中执行时,会创建变量对象的一个 作用域链。作用域链的用途,是保证对执行环境有权访问的所有变量和函数的有序访问。作用域链的前端,始终都是当前执行代码所在环境的变量对象。如果这个环境是函数,则将其活动对象作为变量对象。而下个一变量对象来自包含(外部)环境,一直延续到全局执行环境。全局执行环境的变量对象始终都是作用域链中的最后一个对象。
    标识符解析是沿着作用域链一级一级地搜索标识符的过程。搜索过程始终从作用域链的前端开始,然后逐级地向后回溯,直到找到标识符为止。
    延长作用域链
    |--虽然执行环境的类型总共只有两种——全局和局部(函数),但还是有其他办法来延长作用域链。有些语句可以在作用域链前端临时增加一个变量对象,该变量对象会在代码执行后被移除:
    |--try-catch语句的catch块
    |--with语句
    |--以上两个语句都会在作用域链的前端添加一个变量对象,对with来说,会将指定的对象添加到作用域链中。对catch来说,会创建一个新的变量对象,其中包含的是被抛出的错误对象的声明。
没有块级作用域
    |--JavaScript没有块级作用域,如if语句块中声明的变量会被添加到当前的执行环境,for语句也是一样。
    |--声明变量:使用var声明的变量会自动被添加到最接近的环境中。在函数内部,最接近的环境就是函数的局部环境;在with语句中,最接近的环境是函数环境。如果初始化变量时没有使用var声明,该变量会被自动添加到全局环境。
垃圾收集
    |--JavaScript具有自动垃圾收集机制,也就是说,执行环境会负责管理代码执行过程中使用的内存。原理:其实很简单,就是找出那些不再使用的变量,然后释放其占用的内存。为此,垃圾收集器会按照固定的时间间隔(或代码执行中预定的收集时间),周期性地执行这一操作。     
    |--局部变量的生命周期:只在函数执行的过程中存在,在这个过程中,会为局部变量在栈(堆)内存上分配相应的空间,以便储存它们的值,直至函数执行结束。
    |--垃圾收集策略
         |--标记清除
              |--JavaScript中最常用的垃圾回收方法是标记清除(mark-and-sweep)。
              |--可以通过翻转特殊的位来记录一个变量何时进入环境,或者使用一个‘进入环境的’变量列表及一个’离开环境的‘变量列表来跟踪哪个变量发生了变化。
         |--引用计数(reference counting)
              |--引用计数的含义是跟踪记录每个值被引用的次数。当一个变量指向一个引用类型值的时候,这个值引用次数为1,如果有另外一个变量指向这个引用类型值时,引用次数加1。相反,如果指向这个值的变量指向另外的值时,这个值的引用次数减1。当这个值的引用次数变成0时,则说明没有办法访问这个值了,因此就可以将其所占用的空间回收。
              |--缺陷:循环引用(互相引用对方的引用),可以手工断开,让其指向其他对象,如null。
性能问题
    |--垃圾收集器是周期性运行的,而且如果为变量分配内存数量客观,那么回收工作量也是相当大的。在这种情况下,确定垃圾回收的时间间隔是一个十分重要的问题。
管理内存
    |--分配给web浏览器的内存通常会比分配给桌面应用程序要少,这是出于安全方面考虑,为了防止运行JavaScript的网页耗尽系统内存而导致系统崩溃。内存限制问题不仅会影响给变量分配内存,同时会影响调用栈以及在一个线程中能够同时执行的语句数量。因此,确保占用最少的内存可以让页面获得更好的性能。而优化内存占用的最佳方式,就是为执行中的代码只保存必要的数据。一旦数据不再有用,最好通过将其设置为null来释放其引用——解除引用(dereferencing)。解除引用并不意味着自动回收该值所占用的内存,而是让值脱离执行环境,以便垃圾收集器下次运行时将其回收。





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值