转JavaScript变量、作用域、内存、垃圾回收 var a=1; a=null;
2018-01-04 16:05
246 查看
http://blog.csdn.net/qq_31280709/article/details/52240295
1.基本类型和引用类型
基本类型:简单的数据段,5种基本数据类型Undefined Null String Number Boolean。基本数据类型是按值访问的,因为可以操作保存在变量中的实际的值。在内存中占据固定大小空间,因此保存在栈内存中。
引用类型:可能由多个值构成的对象。引用类型的值是保存在内存中的对象。JS不允许直接访问内存中的位置,不能直接操作对象的内存空间。操作对象时实际是操作对象的引用,而不是实际的对象。->引用类型是按引用访问的(这种说法不严密,当复制保存对象的变量时,操作的是对象的引用,而给对象添加属性时,操作的是实际的对象)包含引用类型值的变量包含的不是对象本身,而是一个指向该对象的指针。保存在堆内存中。
两种类型的差异:
a.添加属性。引用类型可以给对象添加属性,值类型不能添加属性
b.复制变量值。从一个变量向另一个变量复制基本类型的值时,会在变量对象上创建一个新值,然后把该值复制到为新变量分配的位置上。两个变量相互独立,独立操作互不影响。复制引用类型的值时,同样也会将存储在变量对象中的值复制一份放在为新变量分配的空间中。不同的是,这个值的副本是一个指针,指向存储在堆中的一个对象,复制完毕后,两个变量实际引用一个对象。两个变量相互影响。
c.传递参数。ES中所有函数的参数都是按值传递的。将函数外部值复制给函数参数时,就如同复制变量值一样。基本类型的比较好理解就不说了,但对象传递该如何理解?
[javascript]
view plain
copy
function setName(obj) {
obj.name = "Mike";
}
var person = new Object;
setName(person);
alert(person.name);//Mike
咋一看,这好像是引用传递啊。实际上,还是按值传递的。但即使这个变量是按值传递,也会按引用来访问堆中的同一个对象。因此会产生影响到了函数作用域外的现象。为证明,看如下
[javascript]
view plain
copy
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语句 这两种语句时,作用域链会得到加长。
没有块级作用域:
[javascript]
view plain
copy
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来释放其引用----解除引用。这一做法适用于大多数全局变量和全局对象的属性,局部变量在离开执行环境时自动解除引用。
1.基本类型和引用类型
基本类型:简单的数据段,5种基本数据类型Undefined Null String Number Boolean。基本数据类型是按值访问的,因为可以操作保存在变量中的实际的值。在内存中占据固定大小空间,因此保存在栈内存中。
引用类型:可能由多个值构成的对象。引用类型的值是保存在内存中的对象。JS不允许直接访问内存中的位置,不能直接操作对象的内存空间。操作对象时实际是操作对象的引用,而不是实际的对象。->引用类型是按引用访问的(这种说法不严密,当复制保存对象的变量时,操作的是对象的引用,而给对象添加属性时,操作的是实际的对象)包含引用类型值的变量包含的不是对象本身,而是一个指向该对象的指针。保存在堆内存中。
两种类型的差异:
a.添加属性。引用类型可以给对象添加属性,值类型不能添加属性
b.复制变量值。从一个变量向另一个变量复制基本类型的值时,会在变量对象上创建一个新值,然后把该值复制到为新变量分配的位置上。两个变量相互独立,独立操作互不影响。复制引用类型的值时,同样也会将存储在变量对象中的值复制一份放在为新变量分配的空间中。不同的是,这个值的副本是一个指针,指向存储在堆中的一个对象,复制完毕后,两个变量实际引用一个对象。两个变量相互影响。
c.传递参数。ES中所有函数的参数都是按值传递的。将函数外部值复制给函数参数时,就如同复制变量值一样。基本类型的比较好理解就不说了,但对象传递该如何理解?
[javascript]
view plain
copy
function setName(obj) {
obj.name = "Mike";
}
var person = new Object;
setName(person);
alert(person.name);//Mike
咋一看,这好像是引用传递啊。实际上,还是按值传递的。但即使这个变量是按值传递,也会按引用来访问堆中的同一个对象。因此会产生影响到了函数作用域外的现象。为证明,看如下
[javascript]
view plain
copy
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语句 这两种语句时,作用域链会得到加长。
没有块级作用域:
[javascript]
view plain
copy
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来释放其引用----解除引用。这一做法适用于大多数全局变量和全局对象的属性,局部变量在离开执行环境时自动解除引用。
相关文章推荐
- 【四】JavaScript变量、作用域、内存、垃圾回收
- javascript变量类型、执行环境和作用域、垃圾回收
- Java的垃圾回收机制,GC,和变量的创建和删除的关系(即变量的作用域,for循环中的某个变量,出了for循环再引用就会报错了,因为该变量已经被从内存中删掉了)
- 细说JVM系列:自动内存管理内存回收:垃圾收集理论-垃圾收集算法
- Java内存分配及垃圾回收
- JavaScript 的垃圾回收与内存泄露
- 【python】理解python里的赋值、引用、拷贝及作用域、内存管理、垃圾回收
- JVM内存模型与垃圾回收机制
- 读书笔记之--Java虚拟机精讲第六章内存分配与垃圾回收
- jvm的stack和heap,JVM内存模型,垃圾回收策略,分代收集,增量收集
- java方法中把对象置null,到底能不能加速垃圾回收
- Java内存与垃圾回收调优
- PHP垃圾回收机制防止内存溢出
- 堆内存设置以及垃圾回收方式
- JVM学习---JVM内存结构、垃圾回收
- java内存垃圾回收模型
- Java内存与垃圾回收调优
- JVM内存模型以及垃圾回收
- 垃圾回收器的基本原理是什么?垃圾回收器可以马上回收内存吗?有什么办法主动通知虚拟机进行垃圾回收?
- JVM学习笔记(1、 基本结构;2、Java代码编译和执行的整个过程3、内存管理和垃圾回收 4、 内存调优 )