基本类型和引用类型的值
ECMASript中的变量包括两种类型:基本类型和引用类型。基本类型值在内存中占据的空间是固定的,因此被保存在栈内存中。引用类型的值是对象,大小是不固定的,保存在堆内存中。
- 复制变量值
基本类型的复制,可以理解为copy,直接复制一个值然后赋值给变量。两者互不影响。如图:
引用类型的复制,也会将存储在变量中的值复制给另外一个变量。但是这个值是“指针”。两个变量的指针都指向存放在堆内存中的同一个对象。例如:
- 参数传递
函数中参数传递都是按值传递。当然,引用类型的值也是“指针”。函数中的参数可以理解为一个局部变量。而局部变量会在函数执行完之后就会被销毁。
- 引用类型的类型检测
let arr = [];
let fun = function () {
console.log('fun...')
};
let obj = {};
console.log(arr instanceof Array) // true
console.log(fun instanceof Function) // true
console.log(obj instanceof Object) //true
执行环境及作用域
- 执行环境定义了变量和函数有权访问的数据,每个执行环境都有一个与之对应的环境变量对象。环境中的定义的所有变量和函数都挂载到这个环境变量对象中。对开发者不可见,处理器在处理数据的时候会用到它。
- 某个执行环境在运行完毕之后,该执行环境的所有变量和函数会被销毁。
- 代码在一个环境中执行的时候,会为该环境变量对象创建一个作用域,作用域保证了该执行环境对变量和函数的访问顺序和规则。(当前环境的变量和函数优先级最高,然后层层向上访问,直到找不到为止)。例:
// 这里可以访问window的执行环境。内部的执行环境可以访问他外部的执行环境,而外部的执行环境则不可以访问内部的执行环境的变量和函数
var name = 'window'
function out() {
//这里可以访问out->window的执行环境
var name = 'out function...'
function inner() {
//这里可以访问inner->out->window的执行环境
var name = 'inner function...'
console.log('inner: ', name)
}
console.log('out: ', name)
inner()
}
out()
console.log(name)
//结果
//out: out function...
//out: inner: inner function...
//out: window
- 没有块级作用域
块就是{},例如:
if(true) {
}
这个说法现在有点问题,应该说ES5只有全局作用域和函数作用域,没有块级作用域。es6新增的let和const是由块级作用域的概念的。函数是有作用域的,可以称之为“函数作用域”
垃圾回收
javascript具有自动的垃圾回收机制。有两种回收机制:标记清除和引用计数。
- 标记清除
变量进入环境时,被标记为“进入环境”。变量离开时,标记为“变量离开”。
- 引用计数
跟踪记录每一个值被引用的次数。声明了一个变量并将一个引用类型的值赋值给该变量时,引用次数+1。如果同一个值又被赋值给另外一个变量,引用次数+1。如果包含这个值的变量又引用了另外一个值,则次数-1.
- 管理内存
解除引用 如果数据不在有用,手动将其值设置为null可以释放引用。以便垃圾收集器下次运行时将其回收。
引用
javascript高级程序第三版