学习目标
- 理解基本类型和引用类型的值
- 理解执行环境
- 理解垃圾收集
JavaScript松散类型的本质,决定了它只是在特定时间用于保存特定的值的一个名字而已。由于不存在定义某个变量必须保存何种数据类型值的规则,变量的值,�及其数据类型可以在脚本的声明周期内改变。
js中包括两种不同数据类型的值
- 几本类型值 (
undefined
null
string
number
boolean
) - 引用类型值 (
对象
)
这节说了一个问题,只能给引用类型的值动态地添加属性,不能给基本类型的值添加。
两种数据类型,除了保存方式不一样之外,在从一个变量向另一个变量复制基本类型值和引用类型值时,也存在不同。
- 如果从一个变量向另一个变量复制基本类型的值,会在变量对象上创建一个新值,然后把该值复制到为新变量分配的位置上。
var num1 = 5
var num2 = num1
看下图
- 当用一个�变量向另一个变量�复制�引用类型的值的时候,同样也会将存储在变量对象中的值�复制一份放到新变量分配的空间中,不同的是,这个值的副本实际上是一个指针,而这个指针�指向存储在堆中的一个对象,复制操作结束之后,两个变量实际上将引用�同一个对象。所以只要改变其中一个变量就会�影响到另一个变量。
var obj1 = new object()
var obj2 = obj1
ibj1.name = 'qianlongo'
alert(obj.name) // qianlongo
基本原理看下图
ECMAScript中�所有函数的参数都是按值传递的,也就是说,把函数外部的值复制给函数内部的参数,就和把值从一个变量复制到另一个变量一样。
理解上面这句话,大概就可以理解js中的传参机制了,还有可以可以把函数的参数想象成局部变量。
要检测一个变量是不是基本数据类型的?typeof是得力的工具,更具体一些旧事typeof可以确定一个变量是string、number、boolean、还是undefined,但是null会返回object。
- try catch
- with
在类似C语言中,由花括号封闭的代码块都有自己的作用域,因而支持根据条件来定义变量。
if (true) {
var color = 'blue'
}
alert(color) // blue
如果在�类似c语言中,if执行之后变量color会被销毁,但是在js中会被添加到当前的执行环境中。
声明函数
使用var声明的变量会自动添加到最接近的环境中,在函数内部,最接近的环境就是函数局部环境,在with语句中,最接近的环境是函数环境,如果初始化的时候没有制定var声明,该变量就会被添加到全局环境中。
查询标志符
说白了就是js在查找变量的过程是逐级向上的。
var color = 'blue'
function getColor () {
return color
}
alert(getColor()) // blue
JavaScript有自动的垃圾回收机制,执行环境会自动管理代码执行过程中使用的内容。
垃圾回收机制的基本原理
找出那些�不再继续使用的变量,然后释放其占用的内存。�为此,垃圾收集器会按照固定的时间间隔周期性地执行这一操作
垃圾回收机制一般有两种,标记清除
引用计数
基本原理
当变量进入环境(�例如: 声明一个变量),就将这个变量标记为"进入环境",当变量离开环境时将其标志为"离开环境"
基本原理
引用计数的含义是跟踪记录每个值被引用的次数。
- 当声明了一个变量并将一个引用类型的值赋给该变量时,则这个值的引用次数就是1,如果同一个值又被赋给另一个变量,则该引用次数又加一.
- 相反如果包含这个值引用的变量又取得了�另外一个值,则这个值的引用次数减一。
- 当这个值的引用次数变成0的时,则说明没有办法再访问这个值了,因而就可以将其占用的内存空间回收回来。
引用计数带来的问题
function problem () {
var objectA = new object()
var objectB = new object()
objectA.somOtherObject = objectB
objectB.somOtherObject = objectA
}
这个例子中两个对象通过各自的属性相互引用,导致这两个对象的引用次数都是2,且永远不可能为0。在菜用标记清除的策略中,函数执行完成之后,两个对象都离开的作用域,所以循环引用不是问题。
ie中的麻烦
ie中的BOM和DOM对象不是JavaScript对象,而是使用�c++以COM(Component Object Model 组件对象模型)对象形成的。�但是COM对象的垃圾收集机制是引用计数,所以即使ie的JavaScript引擎室使用标记清楚策略来实现的,但是因为存在上面的问题,依然会有循环引用带来的问题。
var element = document.getElementById('some_element')
var myObject = new Object()
myObject.element = element
element.someObject = myObject
为了避免以上问题,应该手动断原声js对象与DOM元素之间的连接
myObject.element = null
element.someObject = null
主要说垃圾回收机制周期处理时间
将不用的变量手动设置为null,解除引用关系。