这是前端面试中几乎必考的一题,最清晰、最能拿高分的版本。
面试官常问问题
- 什么是原型(prototype)?
- 什么是
__proto__? - 什么是构造函数?
- 什么是原型链?为什么 JS 能实现继承?
- 画出原型链图?
1. prototype(原型)是什么?
每一个函数(Function)在创建时,都会自动带有一个 prototype 属性。
这个属性是一个对象,用来存放实例共享的属性和方法。
示例:
javascript
function Person() {}
Person.prototype.sayHi = function() {
console.log("hi")
}
Person.prototype是所有 Person 实例共同"继承"的地方。
2. 什么是 __proto__?
每一个对象都有一个 __proto__ 属性,指向它的原型(即构造函数的 prototype)。
示例:
javascript
const p = new Person()
console.log(p.__proto__ === Person.prototype) // true
__proto__= 实例 → 原型对象的连接- 注意:
__proto__是浏览器实现的,不是规范,但现代浏览器都支持。
3. 构造函数是什么?
构造函数就是使用 new 调用的函数。
javascript
function Person() {}
const p = new Person()
new 做了四件事:
- 创建空对象
{} this指向这个新对象- 新对象的
__proto__ = 构造函数.prototype - 返回这个对象
原型链关系就是在这一步创建的。
4. 什么是原型链?为什么叫链?
当你访问一个对象的属性时:
- 先从自己身上找
- 找不到就去它的
__proto__(原型)上找 - 原型上再找不到就继续向上一层找
- 最终找到
Object.prototype - 再找不到就是
null------ 链结束
因此叫 原型"链"。
示例:
javascript
p.sayHi()
查找顺序:
p → p.__proto__ → Person.prototype → Object.prototype → null
这就是 JS 的继承方式(基于原型链的继承)。
5. 完整原型链图
基础原型链:
javascript
p
↑
__proto__
|
Person.prototype
↑
__proto__
|
Object.prototype
↑
__proto__
|
null
完整原型链(包含 Function):
javascript
Person
↑
__proto__
|
Function.prototype
↑
__proto__
|
Object.prototype
↑
__proto__
|
null
面试官会很满意这样的回答。
6. 原型链常见面试题
❓ 题 1:为什么所有对象都能访问 toString()?
因为 toString() 定义在:
javascript
Object.prototype.toString
所有对象最终都能顺着原型链找到它。
❓ 题 2:为什么数组能访问 push?
因为 push 定义在:
javascript
Array.prototype.push
并且:
ini
arr.__proto__ === Array.prototype
❓ 题 3:函数的原型链是什么?
javascript
function Foo(){}
Foo.__proto__ === Function.prototype
Function.prototype.__proto__ === Object.prototype
Object.prototype.__proto__ === null
速记卡片版
🔶 速记卡:原型(prototype)
- 每一个"函数"天生自带
prototype属性 - 存放实例共享的方法
new时会把实例的__proto__指向它
🔶 速记卡:__proto__
- 每一个对象都有
__proto__ - 指向构造函数的
prototype - 连接对象 → 原型 → 再上一层原型
🔶 速记卡:原型链
- 查找属性的路径
- 自身 → 原型 →
Object.prototype→null - JS 继承的本质
🔶 速记卡:new 的四步
- 创建
{} this = {}{}.__proto__ = 构造函数.prototype- 返回对象