
基本类型和引用类型
-
基本类型
- Undefined
- Null
- Number
- Boolean
- String
- ES6加了一个Symbol
-
引用类型
- 引用类型的值是保存在内存中的对象。与其他语言不通,JavaScript不允许直接防伪内存中的位置,也就是说不能直接操作对象的内存空间。在操作对象时,实际上是在操作对象的引用而不是实际的对象
访问变量有按值和按引用两种方式,而参数只能按值传递
function setName(obj){
obj.name = 'Nicholas'
obj = new Object()
obj.name = 'Greg'
}
var person = new Object()
setName(person)
console.log(person.name) //'Nicholas'
说明即使在函数内修改了参数的值,但原始的引用仍然保持未变。实际上,当在函数内部重写obj时,这个变量利用的就是一个局部对象了。而这个局部对象会在函数执行完毕后立即被销毁。
总结:说明了变量是按值传递的,而不是按引用传递的。
检测类型
typeof
注意 :
typeof null = object
- 使用 typeof 操作符检测函数时,该操作符会返回'function'。
- ECMA-262规定任何在内部实现[[Call]]方法的对象都应该在应用typeof操作符时返回'function',在Safari 5 及之前版本和Chrome 7 及之前版本中使用typeof检测正则表达式时,由于规范的原因,这个操作符也返回‘function’
- 在IE和Firefox中,对正则表达式应用typeof会返回'object'
- 检测基本数据类型时typeof是非常得力的助手
- 检测引用类型的值时,这个操作符的用处不大,这个时候一般用 instanceof 操作符
person instanceof Object //变量perison是Object吗
colors instanceof Array //变量colors是Array吗
pattern instanceof RegExp //变量pattern是RegExp吗
- 如果使用instanceof操作符检测基本类型的值,则该操作符始终会返回false,因为基本类型不是对象
执行环境及作用域
执行环境
- 在Web浏览器中,全局执行环境被认为是window对象
- 某个执行环境中的所有代码执行完毕后,该环境被销毁,保存在其中的所有变量和函数定义也随之销毁
- 每个函数都有自己的执行环境。当执行流进入一个函数时,函数的环境就会被推入一个环境栈中,在函数执行之后,栈将其环境弹出
作用域链
- 作用域链的用途,是保证对执行环境有权访问的所有变量和函数的有序访问。
延长作用域链
执行流进入下列任何一个语句时,作用域链就会得到加长
- try-catch语句的catch块
- with语句
没有块级作用域
垃圾收集
JavaScript程序所需内存的分配以及无用内存的回收完全实现了自动管理。
原理:找出那些不再继续使用的变量,然后释放其占用的内存。 垃圾收集器会按照固定的时间间隔(或代码执行中预定的手机时间),周期性地执行这一操作
垃圾收集器必须追踪哪个变量有用哪个变量没用,对于不再有用的变量打上标记,以备将来收回其占用的内存
-
通常有两个策略
-
标记清除
当变量进入环境时,就将这个变量标记为'进入环境',从逻辑上讲,永远不能释放进入环境的变量所占用的内存。当变量离开环境时,则将其标记为'离开环境' -
引用计数
引用计数的含义是跟踪记录每个值被引用的次数
引用计数有一个很严重的问题,就是当遇到循环引用的时候
-
标记清除
function problem(){
var objectA = new Object()
var objcetB = new Object()
objectA.object = objectB
objectB.anotherObject = objectA
}
IE中又一部分的对象并不是原生JavaScript对象,其BOM和DOM中的对象就是使用C++以COM(Component Object Model,组件对象模型),而COM对象的垃圾收集机制采用的就是引用计数策略,就会存在循环引用的问题
var element = document.getElementById('some_element')
var myObject = new Object()
myObject.element = element
element.someObject = myObject
即使例子中的DOM从页面中移除,它也永远不会被回收
避免类似的循环引用问题,最好是在不使用他们的时候手工断开连接
myObject.element = null
element.someObject = null
为了解决上述问题,IE9把BOM和DOM对象转换成了真正的JavaScript对象。这样就避免了两种垃圾收集算法并存导致的问题,也消除了常见的内存泄漏现象。
性能问题
- 垃圾收集器是周期性运行的
- IE的垃圾收集器是根据内存分配量运行的,达到256个变量、4096个对象(或数组)字面量和数组元素(slot)或者64kb的字符串,垃圾收集器就会运行。如果一个脚本中包含那么多变量,那么该脚本很可能会在其生命周期中一直保有那么多的变量。
- IE7的发布,JavaScript引擎的垃圾收集例程改变了工作方式:触发垃圾收集的变量分配,字面量和数组元素的临界值被调整为动态修正。
- 在IE中,调用
window.CollectGarbage()方法会立即执行垃圾收集 - 在Opera7及更高版本中,调用
window.opera.collect()也会启动垃圾收集例程
管理内存
浏览器的可用内存数量通常要比分配给桌面应用程序的少。这样做的目的主要出于安全方面的考虑,目的是防止运行JavaScript的网页耗尽全部系统内存而导致系统崩溃。
- 优化内存占用的最佳方式,就是为执行中的代码只保存必要的数据。一旦数据不再有用,最好通过将其值设置为null,来释放其引用——这个做法叫做解除引用
function createPerson(name){
var localPerson = new Object()
localPerson.name = name
return localPerson
}
var globalPerson = createPerson('Nicholas')
//解除
globalPerson = null