第四章:变量、作用域和内存问题

基本类型和引用类型的值

ECMASript中的变量包括两种类型:基本类型和引用类型。基本类型值在内存中占据的空间是固定的,因此被保存在栈内存中。引用类型的值是对象,大小是不固定的,保存在堆内存中。

  • 复制变量值

基本类型的复制,可以理解为copy,直接复制一个值然后赋值给变量。两者互不影响。如图:


第四章:变量、作用域和内存问题_第1张图片
基本类型的复制

引用类型的复制,也会将存储在变量中的值复制给另外一个变量。但是这个值是“指针”。两个变量的指针都指向存放在堆内存中的同一个对象。例如:


第四章:变量、作用域和内存问题_第2张图片
引用类型的复制
  • 参数传递

函数中参数传递都是按值传递。当然,引用类型的值也是“指针”。函数中的参数可以理解为一个局部变量。而局部变量会在函数执行完之后就会被销毁。

  • 引用类型的类型检测
  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

执行环境及作用域

  1. 执行环境定义了变量和函数有权访问的数据,每个执行环境都有一个与之对应的环境变量对象。环境中的定义的所有变量和函数都挂载到这个环境变量对象中。对开发者不可见,处理器在处理数据的时候会用到它。
  2. 某个执行环境在运行完毕之后,该执行环境的所有变量和函数会被销毁。
  3. 代码在一个环境中执行的时候,会为该环境变量对象创建一个作用域,作用域保证了该执行环境对变量和函数的访问顺序和规则。(当前环境的变量和函数优先级最高,然后层层向上访问,直到找不到为止)。例:
// 这里可以访问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高级程序第三版

你可能感兴趣的:(第四章:变量、作用域和内存问题)