面试官一问"什么是原型",我脑子就一团浆糊;
更狠的是,他紧接着抛出"原型链"------直接当场短路!
如果你也有这种感觉,别急,跟着我学!。"
一切从一条链开始:原型链是个什么"链"?
说原型链是个"链",其实不是炼金术的那种,是 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 临时"借"了一个对象给它用了一下!
真相只有一个:
只有对象才有原型!!
原始类型(number
、string
、boolean
、null
、undefined
、symbol
、bigint
)
本质上是没有原型的!
能调用方法是因为 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 会偷偷"装箱"为对象临时用
终章彩蛋:测测你掌握没!速速回答!
-
let obj = {};
obj.__proto__
是什么? -
function Foo() {}; let a = new Foo();
a.__proto__
和Foo.prototype
有什么关系? -
为什么说原型链是一种"查找机制"?
-
Object.create(null)
创建的对象可以使用toString()
吗?为什么? -
Number(1)
和new Number(1)
有什么区别?