基本数据类型是按值访问的,由于能够操做保存在变量中的实际的值javascript
基本类型值在内存中占据固定大小的空间,所以被保存在栈内存中前端
引用类型的值是保存在内存中的对象。JavaScript不容许直接访问内存中的位置,也就是说不能直接操做对象的内存空间。在操做对象时,其实是在操做对象的引用而不是实际的对象。为此,引用类型的值是按引用的。java
以上关于引用类型的说法不严密,当复制保存着对象的某个变量时,操做的是对象的引用。但在为对象添加属性时,操做的是实际的对象
引用类型的值是对象,保存在堆内存中算法
不能给基本类型的值添加属性,尽管这样作不会致使任何错误函数
从一个变量向另外一个变量复制基本类型的值,会建立这个值的一个副本指针
包含引用类型值的变量实际上包含的并非对象自己,而是一个指向该对象的指针code
ECMAScript中全部函数的参数都是按值传递的。也就是说,把函数外部的值复制给函数内部的参数,就和把值从一个变量复制到另外一个变量同样对象
肯定一个值是哪一种基本类型能够使用typeof
操做符,而肯定一个值是哪一种引用类型能够使用instanceof
操做符ip
console.log(typeof s); //检测变量s是哪一种基本类型值 console.log(colors instanceof Array); //检测变量colors是否引用类型Array
每一个环境都有一个与之关联的变量对象,环境中定义的全部变量和函数都保存在这个对象中。虽然咱们编写的代码没法访问这个对象,但解析器在处理数据时会在后台使用它内存
执行环境的类型总共只有两种——全局和局部(函数)
,可是还有其余办法来延长做用域链
如下两个语句都会在做用互联的前端添加一个变量对象:
try-catch语句的catch块
catch
会建立一个新的变量对象,其中包含的是被抛出的错误对象的声明
with语句
with
语句会将指定的对象添加到做用域链中
在if
或者for
语句中定义的变量在代码块执行结束后,会存在于代码块外部的执行环境中
垃圾收集器在运行的时候会给储存在内存中的全部变量都加上标记(固然,能够使用任何标记方式)。而后,它会去掉环境中的变量以及被环境中的变量引用的变量的标记。而在此以后再被加上标记的变量被视为准备删除的变量,缘由是环境中的变量以及没法访问到这些变量了。最后,垃圾收集器完成内存清除工做,销毁那些带标记的值并回收它们所占用的内存空间
"标记清除"是目前主流的垃圾收集算法
引用计数的含义是跟踪记录每一个值被引用的次数。当声明了一个变量并将一个引用类型值赋给该变量时,则这个值的引用次数就是1。若是同一个值又被赋给另外一个值,则这个值的引用次数减1。当这个值的引用次数变成0时,则说明没有办法再访问这个值了,于是就能够将其占用的内存空间回收回来
这种引用计数策略存在一个严重的问题:循环引用
function problem(){ var objectA = new Object(); var objectB = new Object(); objectA.someOtherObject = objectB; objectB.anotherObject = objectA; }
上面例子中,objectA和objectB经过各自的属性互相引用,它们的引用次数永远不会是0。假如这个函数被重复屡次调用,就会致使大量内存得不到回收
一旦数据再也不有用,最好经过将其值设置为null来释放其引用——这个作法叫作解除引用(dereferencing)
function createPerson(name){ var localPerson = new Object(); localPerson.name = name; return localPerson; } var globalPerson = createPerson("Nicholas"); globalPerson = null; //手工解除globalPerson的引用
解除一个值得引用并不意味着自动回收该值所占用的内存。解除引用的真正做用是让值脱离执行环境,以便垃圾收集器下次运行时将其回收