看完就懂、懂完就敢讲的「原型与原型链」终极八卦!

面试官一问"什么是原型",我脑子就一团浆糊;

更狠的是,他紧接着抛出"原型链"------直接当场短路!

如果你也有这种感觉,别急,跟着我学!。"


一切从一条链开始:原型链是个什么"链"?

说原型链是个"链",其实不是炼金术的那种,是 JS对象的查找机制(祖宗查找路线图)~

例如: 当你访问 obj.name 却发现 obj 本人没有 name 属性时,JS 会很体贴地说:

"没事,我给你找找祖宗有没有。"

于是它就去 obj.__proto__ 看有没有,再没有继续往上找,一直找,直到找到 null 为止(也就是祖宗尽头)。

所以,原型链其实就是------

一套 JS 对象的"家庭树查找机制"

prototype 和 proto:听着像双胞胎,其实职责不同!

一个是"模子",一个是"指针",虽然有关联,但分工不同。

js 复制代码
function Foo() {}
let a = new Foo();

我们先捋一下:

谁? 是啥? 对谁有用?
Foo.prototype Foo 构造函数的"原型对象" 以后你 new 出的每一个实例
a.__proto__ a 实例的"原型指针" 它指向 Foo.prototype
a.__proto__ === Foo.prototype ✅ true 所以他们确实有点关系

一道"诈人"的代码题

ini 复制代码
function Person() {}
Person.prototype.name = 'person';
Person.prototype = { age: 18 };
let p = new Person();

console.log(p.name); // ❌ undefined
console.log(p.age);  // ✅ 18

很多人看到第一行就以为 p.name === 'person',其实不然!

perl 复制代码
注意:你给 `Person.prototype.name` 设置了属性,
但下一行直接用 `Person.prototype = { age: 18 }` 完全替换了原型对象。
原来的那个"带 name 的旧 prototype"已经无效了!

思考一下?

JS 里只有对象有原型吗?

3

2

1

先看下面这段代码:

ini 复制代码
let a = 12;
console.log(a.toFixed(2)); 

你是不是会想:

"咦?a 是个数字,是原始类型啊,怎么还能调用 .toFixed() 呢?"

难道说......
原始类型也有原型链?也能挂方法?

答案是:看起来是这样,其实并不是!

幕后发生了一件小事:

javascript 复制代码
// 背地里偷偷干了这事:
a = new Number(12);
// 然后你调用 .toFixed()
// 用完立即销毁包装对象

所以你看到的 .toFixed() 并不是原始值 12 的"本事",

而是 JS 临时"借"了一个对象给它用了一下!


真相只有一个:

只有对象才有原型!!

原始类型(numberstringbooleannullundefinedsymbolbigint

本质上是没有原型的!

能调用方法是因为 JS 自动进行了"装箱"操作(装成对应的包装对象)。

那再思考一下?

所有对象都有原型吗?

3

2

1

我们都知道:

vbscript 复制代码
const obj = {};
console.log(obj.toString); // function toString() { ... }

没错,对象可以访问 .toString(),因为它继承自 Object.prototype

所以你可能觉得:

"哈?对象天生就有原型啊,这还用问吗?"

但我们来看看这段代码:

javascript 复制代码
const pure = Object.create(null);
console.log(pure.toString); // undefined
console.log(Object.getPrototypeOf(pure)); // null

居然连 .toString() 都没有?!
是的,这货是真的没有原型。

为什么?


✅ 因为我们用了:

javascript 复制代码
Object.create(null);

这是创建一个完全"干净"的对象

Object.prototype 都不继承!

因此它也就没有原型链 ,是一个彻底裸奔的对象

这种对象常常用在需要纯字典结构 的地方,

比如手写一个 Map、作为 key-value 存储,避免和原型链上的属性名冲突。


所以真相只有一个:

不是所有对象都有原型,Object.create(null) 就是个例外!

这也顺便解释了为什么判断一个对象是不是干净的可以这样写:

javascript 复制代码
Object.getPrototypeOf(obj) === null;

原型链为啥叫"查找机制"?

JS 是这样找属性的:

  • 自己有没有

  • 没有就去 __proto__

  • 再找上面......

  • 找到 null,就真的放弃了

一口气背下来系列 ✅

  • ✅ 原型链:JS 找属性的备用路线图
  • __proto__:实例对象的"祖宗指针"
  • prototype:构造函数的"模子",实例对象都从这复制属性
  • ✅ 原型链尽头是 null,不是 undefined
  • ✅ 原始值没有原型,但 JS 会偷偷"装箱"为对象临时用

终章彩蛋:测测你掌握没!速速回答!

  1. let obj = {};
    obj.__proto__ 是什么?

  2. function Foo() {}; let a = new Foo();
    a.__proto__Foo.prototype 有什么关系?

  3. 为什么说原型链是一种"查找机制"?

  4. Object.create(null) 创建的对象可以使用 toString() 吗?为什么?

  5. Number(1)new Number(1) 有什么区别?

相关推荐
sorryhc6 分钟前
React SSR同构渲染方案是什么?
前端·javascript·next.js
真实的菜12 分钟前
面试高频问题
面试·职场和发展·linq
小公主15 分钟前
别再乱用异步了!一文搞懂 Promise 和 async/await 的执行顺序与最佳实践
javascript
南枝异客25 分钟前
电话号码的字母组合
开发语言·javascript·算法
护国神蛙1 小时前
给你一个页面如何定时刷新
前端·javascript·浏览器
一直游到海水变蓝丿1 小时前
el-select下拉框 添加 el-checkbox 多选框
前端·javascript·vue.js
鸡鸭扣2 小时前
25年春招:米哈游运维开发一面总结
运维·面试·求职招聘·运维开发·面经·sre·米哈游
阿奇__2 小时前
element 跨页选中,回显el-table选中数据
前端·vue.js·elementui
努力往上爬de蜗牛2 小时前
vue3 daterange正则踩坑
javascript·vue.js·elementui
谢尔登2 小时前
【React】SWR 和 React Query(TanStack Query)
前端·react.js·前端框架