# 变量、作用域和内存问题
# 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
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
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
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 引擎目前都不在使用这种算法。
- 当代码中存在循环引用现象,'引用计数'算法就会导致问题
- 解除变量的引用不仅有助于消除循环引用现象,而且对垃圾收集也有好处。为了确保有效地回收内存,应该及时解除不再使用的全局对象、全局对象属性以及循环引用变量的引用