第 4 章 变量、作用域与内存
通过变量使用原始值与引用值
理解执行上下文
理解垃圾回收
4.1 原始值与引用值
JavaScript 变量是松散类型。
变量不过是特定时间点一个特定值的名称而已。
ECMAScript 变量包含两种不同类型的数据:原始值和引用值
| 类别 | 原始值 | 引用值 |
|---|---|---|
| 定义 | 最简单的数据(Undefined,Null,Boolean,String和Symbol) | 由多个值构成的对象(Object) |
| 访问方式 | 按值访问(by value) | 按引用访问(by reference) |
| 操作对象 | 存储在变量中的实际值 | 对该对象的引用(reference) |
4.1.1 动态属性
定义的变量是否有动态属性:
引用值:可以随时添加、修改和删除其属性和方法。但原始值不可以。
// 引用值
let person = new Object();
person.name = 'Nicholas';
console.log(person.name); // "Nicholas"
// 原始值
let name = 'Nicholas';
name.age = 27;
console.log(name.age); // "undefined"
注意:原始类型的初始化可以只使用原始字面量形式。如果使用的是 new 关键字,则 JavaScript 会创建一个 Object 类型的实例,但其行为类似原始值。
let name1 = 'Nicholas';
let name2 = new String('Matt');
name1.age = 27;
name2.age = 26;
console.log(name1.age); // undefined
console.log(name2.age); // 26
console.log(typeof name1); // string
console.log(typeof name2); // object
4.1.2 复制值
除了存储方式不同,原始值和引用值在通过变量复制时也有所不同。
// 原始值复制方式
let num1 = 5;
let num2 = num1;
其复制过程如下:
可以看到,这两个变量可以独立使用,互不干扰。
// 引用值复制方式
let obj1 = new Object();
let obj2 = obj1;
obj1.name = 'Nicholas'; // 修改 obj1 的属性
console.log(obj2.name); // "Nicholas"
在把引用值从一个变量赋给另一个变量时,存储在变量中的值会被复制到新变量所在的位置。区别在于,这里复制的值实际上是一个指针,它指向存储在堆内存中的对象。操作完成后,两个变量实际上指向同一个对象。