# 变量、作用域和内存问题

# 4.1 基本类型和引用类型的值

  • 基本类型:undefined, null, Boolean, Numbers, String
  • 引用类型:Object

# 4.1.1 动态的属性

只能给引用类型值动态的添加属性

var a = {}
a.name = '123'

a.name // 123

var b = 123
b.name = 456

b.name // undefined
1
2
3
4
5
6
7
8
9

# 4.1.2 复制变量值

基本数据类型是直接复制,复制后的两个值互不影响。引用数据类型复制的实际是指针,相当于两个变量指向同一个堆内存地址,所以更改一个另一个会更改。

# 4.1.3 传递参数

ECMAScript 中所有函数的参数都是按值传递的。也就是说,把函数外部的值复制给函数内部的参数,就和把值从一个变量复制到另一个变量一样。

// 1.基本数据类型
function add (num) {
  num += 10
  return num
}

var count = 20
var result = add(count)
count // 20 没有变化
result // 30

// 2. 引用数据类型
function setName (obj) {
  obj.name = 'Nicholas'
}
var person = {}
setName(person)
person.name // 'Nicholas'

// 3. 局部变量
function setName (obj) {
  obj.name = 'Nicholas'
  obj = new Object()
  obj.name = 'newming'
}
var person = {}
setName(person)
person.name // 'Nicholas'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

# 4.1.4 类型检测

var a = 1
typeof a

var b = null
typeof b // object

// instanceof 继承
var arr = []
console.log(arr instanceof Array) // true
console.log(arr instanceof Object) // true 注意
1
2
3
4
5
6
7
8
9
10

# 4.2 执行环境及作用域

  • 全局执行环境:window
  • 函数执行环境: function

作用域链

# 4.2.1 延长作用域链

  • try-catch 中的 catch
  • with 语句

# 4.2.2 没有块级作用域

# 4.3 垃圾收集

# 4.3.1 标记清除

# 4.3.2 引用计数

# 4.3.3 性能问题

# 4.3.4 管理内存

# 4.4 小结

  • 基本数据类型值在内存中占据固定大小的空间,因此被保存在栈内存中
  • 从一个变量向另一个变量复制基本类型的值,会创建这个值的一个副本
  • 引用类型的值是对象,保存在堆内存中
  • 包含引用类型值的变量实际上包含的并不是对象本身,而是一个指向该对象的指针
  • 从一个变量向另一个变量复制引用类型的值,复制的其实是指针,因此两个变量最终都指向同一个对象
  • 确定一个值是哪种基本类型可以使用 typeof 操作符,而确定一个值是哪种引用类型可以使用 instanceof 操作符
  • 执行环境有全局执行环境(也称全局环境)和函数执行环境之分
  • 每次进入一个新执行环境,都会创建一个用于搜索变量和函数的作用域链
  • 函数的局部环境不仅有权访问函数作用域中的变量,而且有权访问其包含(父)环境,乃至全局环境
  • 全局环境只能访问在全局环境中定义的变量和函数,而不能直接访问局部环境中的任何数据
  • 变量的执行环境有助于确定应该何时释放内存
  • JavaScript 是一门具有自动垃圾回收机制的编程语言
  • 离开作用域的值将被自动标记为可以回收,因此将在垃圾回收期间被删除
  • '标记清除'是目前主流的垃圾收集算法,这种算法的思想是给当前不使用的值加上标记,然后在回收其内存
  • 另一种垃圾收集算法是'引用计数',这种算法的思想是跟踪记录所有值被引用的次数。JavaScript 引擎目前都不在使用这种算法。
  • 当代码中存在循环引用现象,'引用计数'算法就会导致问题
  • 解除变量的引用不仅有助于消除循环引用现象,而且对垃圾收集也有好处。为了确保有效地回收内存,应该及时解除不再使用的全局对象、全局对象属性以及循环引用变量的引用