【四】JavaScript变量、作用域、内存、垃圾回收

1.基本类型和引用类型

   基本类型:简单的数据段,5种基本数据类型Undefined Null String Number Boolean。基本数据类型是按值访问的,因为可以操作保存在变量中的实际的值。在内存中占据固定大小空间,因此保存在栈内存中。

   引用类型:可能由多个值构成的对象。引用类型的是保存在内存中的对象。JS不允许直接访问内存中的位置,不能直接操作对象的内存空间。操作对象时实际是操作对象的引用,而不是实际的对象。->引用类型是按引用访问的(这种说法不严密,当复制保存对象的变量时,操作的是对象的引用,而给对象添加属性时,操作的是实际的对象)包含引用类型值的变量包含的不是对象本身,而是一个指向该对象的指针。保存在堆内存中。

   两种类型的差异:

      a.添加属性。引用类型可以给对象添加属性,值类型不能添加属性

      b.复制变量值。从一个变量向另一个变量复制基本类型的值时,会在变量对象上创建一个新值,然后把该值复制到为新变量分配的位置上。两个变量相互独立,独立操作互不影响。复制引用类型的值时,同样也会将存储在变量对象中的值复制一份放在为新变量分配的空间中。不同的是,这个值的副本是一个指针,指向存储在堆中的一个对象,复制完毕后,两个变量实际引用一个对象。两个变量相互影响。

      c.传递参数。ES中所有函数的参数都是按值传递的。将函数外部值复制给函数参数时,就如同复制变量值一样。基本类型的比较好理解就不说了,但对象传递该如何理解?

function setName(obj) {
    obj.name = "Mike";
}
var person = new Object;
setName(person);
alert(person.name);//Mike
      咋一看,这好像是引用传递啊。实际上,还是按值传递的。但即使这个变量是按值传递,也会按引用来访问堆中的同一个对象。因此会产生影响到了函数作用域外的现象。为证明,看如下

function setName(obj) {
    obj.name = "Mike";
    obj = new Object();
    obj.name = "Tony";
}
var person = new Object;
setName(person);
alert(person.name);//Mike
      如果是按引用传递,则外部alert时会弹出Tony。然而实际上即使obj = new Object()在函数内部修改了参数的值,但原始的引用没有改变。在函数内部重写obj时,这个变量引用的就是一个局部变量而不是person,这个局部变量在函数执行完毕就销毁。

      ====》所以,参数传递是按值传递,按引用访问

      d.检测类型。typeof检测基本类型,instanceof检测引用类型-->如果变量是给定引用类型的实例(根据它的原型链识别)则instanceof操作符返回true。参考博客JavaScript之一切皆对象

2.执行环境和作用域

   每个执行环境都有一个与之关联的变量对象,环境中定义的所有变量和函数都保存在了这个变量对象中。(代码无法访问这个对象,解析器会在后台处理)

   全局执行环境:是最外围的执行环境。Web浏览器中全局执行环境是window对象-->所有全局变量和函数都是作为window对象的属性和方法创建的。

   程序执行流:当执行流进入一个函数时,函数的环境被推入一个环境栈,函数执行后,栈将其环境弹出,将控制权交给之前的执行环境。

   作用域链:保证对执行环境有权访问的所有变量和函数的有序访问。每次进入一个新执行环境都会创建作用域链。每个环境可以向上搜索作用域链,但任何环境不能向下搜索作用域链进入另一个执行环境。

   延长作用域链:有些语句可以在作用域链的前端临时增加一个变量对象(代码执行后该变量对象会被移除)当执行流进入1:try-catch的catch块 2:with语句 这两种语句时,作用域链会得到加长。

   没有块级作用域

if(true) {
    var color = "blue";
}
alert(color);<span style="color:#FF0000;">//blue</span>
//-------------------------
for(var i = 0;i < 10;i++) {
    //code
}
alert(i);<span style="color:#FF0000;">//10</span>
3.垃圾收集机制

   JavaScript具有自动垃圾收集机制,执行环境会负责管理代码执行过程中使用的内存。原理:找出不再继续使用的变量,然后释放其占用的内存,按固定的时间间隔来周期性执行这操作。用于标识无用变量的策略:

   1.标记清除 常用,主流。思想:给当前不使用的值加上标记。

   2.引用计数 不常用,存在一个严重的问题,循环引用 思想:跟踪记录所有值被引用的次数。


  优化内存占用:一旦数据不再有用,最好通过将其值设置为null来释放其引用----解除引用。这一做法适用于大多数全局变量和全局对象的属性,局部变量在离开执行环境时自动解除引用。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值