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

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

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

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


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

说原型链是个"链",其实不是炼金术的那种,是 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) 有什么区别?

相关推荐
blackorbird8 分钟前
谷歌 Chrome 浏览器的指纹识别技术,一边反追踪一边搞追踪
前端·chrome
在等晚安么10 分钟前
力扣面试150题打卡
算法·leetcode·面试
Mintopia38 分钟前
🚀 共绩算力:3分钟拥有自己的图像优化服务-CodeFormer:先进的图像算法优化、修复马赛克、提升图片清晰度等
前端·人工智能·ai编程
Lhuu(重开版1 小时前
html语法
前端·html
月弦笙音1 小时前
【vue3】这些不常用的API,却很实用
前端·vue.js·面试
小只笨笨狗~1 小时前
css-文字背景渐变色
前端·css·html
BingoGo1 小时前
CSS 也要支持 if 了 !!!CSS if() 函数来了!
前端·css
用户6600676685391 小时前
深入解析JavaScript数组:从内存原理到高效遍历实践
前端·javascript