lesson63:JavaScript 核心概念深度解析:序列化与反序列化、原型与原型链
目录
一、序列化与反序列化:JavaScript 对象的“变形记”
1.2 核心 API:JSON.stringify() 与 JSON.parse()
2.2 原型链(Prototype Chain):属性查找的“瀑布流”
JavaScript 作为前端开发的基石,其独特的数据处理机制和对象模型是构建复杂应用的基础。本文将深入探讨两个核心概念:序列化与反序列化(数据持久化与传输的核心)和原型与原型链(对象继承与共享的底层机制),帮助开发者夯实基础,提升代码设计能力。
一、序列化与反序列化:JavaScript 对象的“变形记”
1.1 概念与核心价值
序列化(Serialization)是将 JavaScript 对象转换为可传输/存储的字符串格式的过程;反序列化(Deserialization)则是其逆过程,将字符串还原为对象。二者共同解决了数据持久化(如本地存储)和跨上下文传输(如网络请求)的核心问题。
1.2 核心 API:JSON.stringify() 与 JSON.parse()
1.2.1 序列化:JSON.stringify()
将对象转换为 JSON 字符串,支持三个参数:
- value:待序列化的对象
- replacer:自定义过滤/转换函数(可选)
- space:格式化缩进空格数(可选,美化输出)
基础用法:
const user = {
name: "John",
age: 30,
roles: ["admin", "editor"],
birthDate: new Date("1995-01-01")
};
const jsonStr = JSON.stringify(user);
// 输出:{"name":"John","age":30,"roles":["admin","editor"],"birthDate":"1995-01-01T00:00:00.000Z"}
高级技巧:
- 过滤敏感字段:通过 replacer 函数排除密码等信息
JSON.stringify(user, (key, value) => { if (key === "password") return undefined; // 过滤密码 return value; }); - 处理特殊类型:Date 对象会自动转为 ISO 字符串,但函数、undefined、Symbol 会被忽略
- 循环引用处理:需自定义检测(如使用 WeakSet 缓存已处理对象)
const obj = { name: "Parent" }; obj.child = { parent: obj }; // 循环引用 const cache = new WeakSet(); JSON.stringify(obj, (key, value) => { if (typeof value === "object" && value !== null) { if (cache.has(value)) return "[Circular]"; cache.add(value); } return value; }); // 输出:{"name":"Parent","child":{"parent":"[Circular]"}}
1.2.2 反序列化:JSON.parse()
将 JSON 字符串还原为对象,支持两个参数:
- text:JSON 字符串
- reviver:自定义还原函数(可选,用于恢复特殊类型)
基础用法:
const parsedUser = JSON.parse(jsonStr);
console.log(parsedUser.roles[0]); // 输出:"admin"
高级技巧:
- 恢复 Date 类型:通过 reviver 函数将字符串转为 Date 对象
const data = JSON.parse('{"date":"2025-05-10T12:00:00.000Z"}', (k, v) => { if (k === "date") return new Date(v); return v; }); console.log(data.date instanceof Date); // 输出:true - 安全解析:避免使用
eval('(' + jsonStr + ')')(存在 XSS 风险),优先使用JSON.parse()
1.3 实战场景与注意事项
典型应用场景:
- 网络传输:API 请求/响应中 JSON 数据的编码与解码
- 本地存储:
localStorage/sessionStorage仅支持字符串存储,需序列化对象// 存储 localStorage.setItem("user", JSON.stringify(user)); // 读取 const savedUser = JSON.parse(localStorage.getItem("user")); - 跨页面通信:通过
postMessage传递对象时需先序列化
常见陷阱:
- 数据类型丢失:函数、undefined、Symbol 会被序列化忽略
- 循环引用报错:直接序列化循环引用对象会抛出
TypeError - 二进制数据处理:需手动转为 Base64 字符串(如 ArrayBuffer → Base64)
二、原型与原型链:JavaScript 对象的“继承基因”
2.1 原型(Prototype):对象的“共享衣橱”
每个 JavaScript 对象(除 null 外)都有一个原型对象,通过 [[Prototype]] 内部属性关联(可通过 Object.getPrototypeOf(obj) 或 obj.__proto__ 访问)。原型对象的属性和方法会被所有关联对象共享继承。
核心关联关系:
- 构造函数的
prototype属性:指向实例对象的原型 - 实例对象的
__proto__属性:指向构造函数的prototype - 原型对象的
constructor属性:指回关联的构造函数
代码示例:
function Person(name) {
this.name = name; // 实例属性
}
// 原型方法(所有实例共享)
Person.prototype.sayHello = function() {
console.log(`Hello, I'm ${this.name}`);
};
const person = new Person("Alice");
console.log(person.__proto__ === Person.prototype); // true(实例→原型)
console.log(Person.prototype.constructor === Person); // true(原型→构造函数)
2.2 原型链(Prototype Chain):属性查找的“瀑布流”
当访问对象的属性时,JavaScript 会先在对象自身查找;若不存在,则沿 __proto__ 链向上查找原型对象,直至找到或抵达链的终点(Object.prototype.__proto__ === null)。这条查找链即原型链。
原型链的终点与内置原型:
- 顶层原型:
Object.prototype(所有对象的“根原型”) - 内置对象原型:
Array.prototype、String.prototype等,提供内置方法(如array.push()继承自Array.prototype)
属性查找示例:
const arr = [1, 2, 3];
arr.push(4); // 自身无 push → 查找 Array.prototype.push → 找到并执行
arr.toString(); // Array.prototype 无 toString → 查找 Object.prototype.toString → 找到并执行
2.3 原型链的实际应用
1. 实现继承(ES6 class 语法糖的底层机制):
// 父类
function Animal(name) {
this.name = name;
}
Animal.prototype.eat = function() {
console.log(`${this.name} is eating`);
};
// 子类
function Dog(name, breed) {
Animal.call(this, name); // 继承实例属性
this.breed = breed;
}
// 继承原型方法(核心)
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog; // 修复 constructor 指向
const dog = new Dog("Buddy", "Golden Retriever");
dog.eat(); // 输出:"Buddy is eating"(继承自 Animal.prototype)
2. 扩展内置对象功能(谨慎使用):
// 为数组添加去重方法(不推荐直接修改内置原型,可能引发冲突)
Array.prototype.unique = function() {
return [...new Set(this)];
};
[1, 2, 2, 3].unique(); // [1, 2, 3]
3. 理解 instanceof 运算符:
判断对象是否在构造函数的原型链上:
dog instanceof Dog; // true(dog → Dog.prototype → Animal.prototype → Object.prototype)
dog instanceof Animal; // true(原型链包含 Animal.prototype)
三、总结:从数据到对象的 JavaScript 世界观
-
序列化与反序列化解决了数据的“跨时空旅行”问题,是前后端通信、本地存储的基础,掌握
JSON.stringify/JSON.parse的高级用法可应对复杂场景(如循环引用、类型恢复)。 -
原型与原型链是 JavaScript 面向对象的核心,理解其机制能帮助开发者写出更高效的代码(如共享方法减少内存占用),并深入掌握继承、
this指向等底层逻辑。
这两个概念虽看似独立,却共同构成了 JavaScript 处理数据与对象的基石。无论是构建大型应用还是调试复杂问题,扎实的基础都是提升开发效率的关键。
推荐延伸学习:ES6+ 中的 class 语法糖与原型链的关系、WeakMap 解决循环引用序列化问题、Object.setPrototypeOf() 与原型链动态修改。
更多推荐
所有评论(0)