在 JavaScript 中,引用类型(Reference Type)是一个重要的概念,它不同于基本类型(primitive types)。让我们深入探讨引用类型的各个方面。
引用类型指的是对象(object)类型,包括:
{}
[]
function() {}
new Date()
new RegExp()
与基本类型(数字、字符串、布尔、null、undefined、Symbol、BigInt)不同,引用类型的值是存储在内存中的对象,变量实际上存储的是对该对象的引用(内存地址),而不是对象本身。
动态属性:可以随时添加、修改或删除属性
let person = {};
person.name = "John"; // 添加属性
person.age = 30; // 添加属性
按引用传递:赋值或传递时传递的是引用,不是值的副本
let obj1 = { a: 1 };
let obj2 = obj1; // obj2和obj1引用同一个对象
obj2.a = 2;
console.log(obj1.a); // 输出2,因为修改的是同一个对象
比较的是引用:两个对象即使内容相同,也不相等
let a = { value: 1 };
let b = { value: 1 };
console.log(a === b); // false,因为引用不同
创建对象的方式:
// 对象字面量
let person = {
name: "John",
age: 30,
sayHi: function() {
console.log("Hi!");
}
};
// 构造函数
let person = new Object();
person.name = "John";
数组是特殊的对象,具有数字索引和length属性:
let colors = ["red", "green", "blue"];
colors[3] = "yellow"; // 添加元素
colors.length = 2; // 截断数组,只保留前两个元素
数组方法:
push/pop
- 末尾添加/删除shift/unshift
- 开头删除/添加splice
- 删除/插入元素slice
- 返回子数组concat
- 合并数组indexOf/lastIndexOf
- 查找元素forEach/map/filter/reduce
- 迭代方法函数也是对象:
function sum(a, b) {
return a + b;
}
// 函数表达式
let sum = function(a, b) { return a + b; };
// 作为值传递
function callSomeFunction(someFunction, someArgument) {
return someFunction(someArgument);
}
日期和时间处理:
let now = new Date(); // 当前日期时间
let someDate = new Date(Date.parse("May 25, 2023"));
let y2k = new Date(2000, 0); // 2000年1月1日
// 常用方法
now.getFullYear(); // 年
now.getMonth(); // 月(0-11)
now.getDate(); // 日(1-31)
now.getDay(); // 星期(0-6)
now.getHours(); // 时
now.getTime(); // 时间戳(毫秒)
正则表达式:
let pattern1 = /[bc]at/i; // 字面量形式
let pattern2 = new RegExp("[bc]at", "i"); // 构造函数形式
// 常用方法
let text = "cat, bat, sat, fat";
let matches = text.match(pattern1); // ["cat"]
let result = pattern1.test(text); // true
特性 | 基本类型 | 引用类型 |
---|---|---|
存储内容 | 实际值 | 内存地址引用 |
存储位置 | 栈内存 | 堆内存 |
大小 | 固定 | 不固定 |
复制行为 | 创建新副本 | 复制引用 |
比较 | 比较值 | 比较引用 |
动态属性 | 不能添加 | 可以动态添加/删除 |
由于引用类型的特性,复制时需要特别注意:
浅拷贝 - 只复制第一层属性:
let obj = { a: 1, b: { c: 2 } };
let shallowCopy = Object.assign({}, obj);
// 或
let shallowCopy = { ...obj };
深拷贝 - 递归复制所有层级:
let deepCopy = JSON.parse(JSON.stringify(obj));
// 或使用递归函数实现完整深拷贝
function deepClone(obj) {
if (obj === null || typeof obj !== "object") return obj;
let clone = Array.isArray(obj) ? [] : {};
for (let key in obj) {
clone[key] = deepClone(obj[key]);
}
return clone;
}
引用类型存储在堆内存中,JavaScript 使用垃圾回收机制自动管理内存。当对象不再被引用时,会被垃圾回收器回收。
let obj = { a: 1 }; // 创建对象,分配内存
obj = null; // 解除引用,对象可被回收
理解引用类型对于掌握 JavaScript 至关重要,特别是在处理复杂数据结构、函数参数传递和内存管理时。