小白也能懂:JavaScript 原型链和隐藏类的奇妙世界

小白也能懂:JavaScript 原型链和隐藏类的奇妙世界

大家好!今天我们来聊聊 JavaScript 里两个听起来高大上但其实很简单的概念:原型链隐藏类。别被名字吓到,我会用最生活化的方式解释给你听!


一、原型链:JavaScript 的"家族族谱" 🧬

想象你有一个玩具箱(对象),你想找某个玩具(属性):

javascript 复制代码
const myToyBox = {
  car: "红色小汽车", // 自己的玩具
};

当你直接找 myToyBox.car,立刻就能找到。但如果想找一个不存在的玩具呢?

javascript 复制代码
console.log(myToyBox.robot); // 自己箱子里没有!

这时 JavaScript 会去"爸爸的玩具箱"里找 → 这就是原型链

javascript 复制代码
// 爸爸的玩具箱
const dadsToyBox = {
  robot: "变形金刚"
};

// 设置爸爸的箱子为你的原型
Object.setPrototypeOf(myToyBox, dadsToyBox);

console.log(myToyBox.robot); // ✅ 找到了变形金刚!

查找过程就像寻宝游戏

  1. 先翻自己的箱子(对象自身)
  2. 找不到就去爸爸的箱子(原型对象)
  3. 还找不到就去爷爷的箱子(原型的原型)
  4. 直到找到或家族尽头(null)

(示意图:对象 → 原型 → 原型的原型 → null)

🔑 关键点 :当你用 对象.属性 时,JavaScript 会沿着这条"家族链"层层查找!


二、原型链是链表吗?底层揭秘 🔍

很多教程说原型链像"链表",对也不对

  • 行为像链表:通过指针连接,顺序查找
  • 实现非链表:引擎用更高级方式优化

看个底层伪代码(V8引擎简化版):

cpp 复制代码
// 当访问 obj.property 时
Object* current = obj;
while (current != null) {
  if (current->HasProperty("property")) {
    return value; // 找到就返回
  }
  current = current->prototype; // 跳转到下一个原型
}
return undefined; // 找不到

就像你按地址串门找人:

javascript 复制代码
你家(对象)→ 爸爸家(原型)→ 爷爷家(Object.prototype)→ 终点(null)

三、隐藏类:引擎的"超强记忆术" 🧠

如果每次查属性都要遍历整条链,岂不慢死?别怕!JavaScript 引擎有个秘密武器------隐藏类

什么是隐藏类?

想象你去学校图书馆:

  • 无隐藏类:每次借书都从头找书名(超慢!)
  • 有隐藏类:管理员记住"科幻区第3书架"(直接拿书)

代码示例

javascript 复制代码
// 创建两个相同结构的对象
const obj1 = {};
obj1.name = "小明"; // 触发隐藏类 C1
obj1.age = 12;     // 转换到隐藏类 C2

const obj2 = {};
obj2.name = "小红"; // 同样触发 C1 → C2 转换

这时引擎会:

  1. {name, age} 结构创建共享的隐藏类
  2. 记录 nameage 在内存中的固定位置
  3. 后续访问时直接跳转地址(比查字典快10倍!)

什么时候会"失忆"?

javascript 复制代码
// ❌ 错误示范:打乱属性顺序
const obj3 = {};
obj3.age = 12;     // 创建新隐藏类 C3
obj3.name = "小刚"; // 转换到 C4(与 obj1/obj2 不同!)

📝 最佳实践

✅ 按固定顺序初始化属性

✅ 尽量在构造函数中赋值

❌ 避免动态增删属性


总结:三句话掌握精髓 💡

  1. 原型链是 JS 的属性查找机制------像家族寻亲,层层向上找
  2. 点操作符(.) 触发原型链遍历------从自己到原型链尽头
  3. 隐藏类是引擎的优化术------用固定内存布局加速访问

下次看到 obj.property,你就知道背后有一段精彩的"寻亲之旅"啦!建议写个简单例子体验一下,代码是最好的老师哦~

javascript 复制代码
// 动手实验!
const grandpa = { hobby: "钓鱼" };
const father = { job: "工程师" };
Object.setPrototypeOf(father, grandpa);

const me = {};
Object.setPrototypeOf(me, father);

console.log(me.hobby); // 试试输出什么?
相关推荐
闲蛋小超人笑嘻嘻7 分钟前
非父子通信: provide和inject
前端·javascript·vue.js
周亚鑫7 分钟前
vue3 js代码混淆
开发语言·javascript·ecmascript
止观止22 分钟前
不止解构:深入掌握 ES6+ 对象与函数的高级语法糖
前端·javascript·es6
捻tua馔...28 分钟前
antd3的表单实现(HOC解决方案)
前端·javascript·react.js
AllinLin40 分钟前
JS中的call apply bind全面解析
前端·javascript·vue.js
POLITE31 小时前
Leetcode 438. 找到字符串中所有字母异位词 JavaScript (Day 4)
javascript·算法·leetcode
创思通信1 小时前
STM32F103C8T6采 DS18B20,通过A7680C 4G模块不断发送短信到手机
javascript·stm32·智能手机
zhougl9961 小时前
vue中App.vue和index.html冲突问题
javascript·vue.js·html
止观止1 小时前
告别全局污染:深入理解 ES Modules 模块化与构建工具
javascript·webpack·vite·前端工程化·es modules
千寻girling1 小时前
面试官: “ 请你讲一下 package.json 文件 ? ”
前端·javascript·面试