面试复盘:谈谈你对 原型、原型链、构造函数、实例、继承的理解

谈谈你对 原型、原型链、构造函数、实例、继承的理解

构造函数(constuctors):为了批量创建对象,我们会用首字母大写的函数来定义构造函数,functon Person(name,age){ this.name = name;this.age = age; }

实例(instances):通过构造函数创建的对象,就是该构造函数的实例 let xiaoming = new Person("小明",18);

new 关键字做了什么:

kotlin 复制代码
使用 new 调用时会做四件事:
创建一个空对象
把这个空对象的 __proto__ 指向构造函数的 prototype
把函数中的 this 指向这个新对象
执行函数体代码(给 this 加属性)
返回这个对象(除非手动返回其他对象)

原型(prototype):每一个构造函数身上会有一个prototype属性,这个属性指向一个对象,这个对象就是我们说的原型对象。

原型链:Preson.prototype == xiaoming.proto

markdown 复制代码
注意:
1、xiaoming 本身没有 .constructor 属性,它是顺着原型链在 xiaoming.__proto__(即 Person.prototype)上找到的。所以 xiaoming.constructor 实际上指向了 Person。
2、"__proto__ 是构造函数的属性"	         ❌ __proto__ 是**实例**的属性
3、"prototype 是所有对象都有"	         ❌ 只有函数有 prototype(箭头函数除外)
4、"constructor 一定是可靠的"	         ❌ 如果原型被替换过(如继承中),必须手动修复
5、"原型链是从 prototype 到 prototype"	 ❌ 是从 __proto__ 到 __proto__ 的链

原型链查找:

javascript 复制代码
当你访问 xiaoming.sayHello 时,引擎会:
查自身属性:首先检查 xiaoming 对象本身是否有 sayHello 属性。
沿链向上:如果没有,就通过 xiaoming.__proto__ 找到 Person.prototype,看这里有没有。
继续向上:如果还没有,就继续通过 Person.prototype.__proto__ 找到 Object.prototype(因为所有对象默认原型链的顶端都是它)。
直到终点:如果 Object.prototype 上还没有,就再通过 Object.prototype.__proto__ 找到 null,然后返回 undefined。

最终一句话总结
当你访问一个对象的属性或方法时,如果它自己没有,JS 就会顺着它的 __proto__ 往上找,一直找到 Object.prototype,再找不到就返回 undefined ------ 这个查找路径,就是**原型链**。

而这一切的基础是:

实例.__proto__ === 构造函数.prototype

es5的继承:

javascript 复制代码
// 父类构造函数
function Animal(name) {
    this.name = name;
    this.type = 'animal';
}

// 父类方法放在原型上
Animal.prototype.eat = function() {
    console.log(this.name + " 在吃东西");
};

// 子类构造函数
function Dog(name, breed) {
    // ✅ 构造函数继承:借用父类构造函数
    Animal.call(this, name);  // 继承实例属性:name, type
    this.breed = breed;       // 子类特有属性
}

// ✅ 原型链继承:建立原型关系
Dog.prototype = Object.create(Animal.prototype);
创建了一个新的空对象
将这个新对象的 __proto__ 指向 Animal.prototype
将这个新对象赋值给 Dog.prototype
这样就建立了正确的原型链关系:

dog 实例对象 
↓ __proto__ 
Dog.prototype (新创建的对象)
↓ __proto__ 
Animal.prototype 
↓ __proto__ 
Object.prototype 
↓ __proto__ 
null

// 注意:不能直接 Dog.prototype = new Animal()
Dog 和 Animal 会共享同一个原型对象
在 Dog.prototype 上添加方法也会影响到 Animal.prototype
Animal 的实例也会获得 Dog 特有的方法,这显然不符合继承的设计意图

// 修正 constructor 指向
Dog.prototype.constructor = Dog;
// 因为 Object.create(Animal.prototype) 创建的新对象的 constructor 属性会指向 Animal,而不是 Dog。修正后才能保证
// 因为 Dog.prototype 被重新赋值了,原来的 constructor 丢了。
// 不修复的话:dog.constructor === Animal ❌
// 修复后:dog.constructor === Dog ✅

// 子类自己添加方法
Dog.prototype.bark = function() {
    console.log(this.name + " 在汪汪叫");
};

// 使用
const dog = new Dog("旺财", "哈士奇");
dog.eat();  // ✅ 调用父类方法 → "旺财 在吃东西"
dog.bark(); // ✅ 调用自己的方法 → "旺财 在汪汪叫"
console.log(dog.type); // ✅ "animal",来自 Animal 构造函数

总结:组合继承的核心步骤
步骤	目的	写法
1️⃣ 构造函数继承	继承父类的实例属性	Animal.call(this, ...)
2️⃣ 原型链继承	继承父类的原型方法	Dog.prototype = Object.create(Animal.prototype)
3️⃣ 修复 constructor	保持 constructor 正确	Dog.prototype.constructor = Dog

ES6 class继承(现代标准)

scala 复制代码
class Parent {
  constructor(name) { this.name = name; }
  say() { console.log(this.name); }
}

class Child extends Parent { // 核心: extends
  constructor(name, age) {
    super(name); // 核心: super 调用父类构造函数
    this.age = age;
  }
}

let c = new Child('Tom', 10);
c.say(); // 'Tom'
相关推荐
枕星而眠2 小时前
C++ 类与对象核心知识点及面试高频题详解
开发语言·c++·面试
Lee川7 小时前
Milvus 实战:当 RAG 遇上向量数据库,从"玩具 Demo"到"生产可用的"那一步
前端·数据库·人工智能
anOnion8 小时前
构建无障碍组件之Toolbar Pattern
前端·html·交互设计
惊鸿一博8 小时前
图标加载方式_zeroIcon_是否加前缀mdi
开发语言·前端·javascript
2501_940041748 小时前
前端工程化进阶:5个高交互与可视化项目提示词
前端
你很易烊千玺8 小时前
JS 异步 从零讲(大白话 + 真实场景 + 可运行案例)
前端·javascript·vue.js
华洛10 小时前
讲讲如何在传统产品中挖掘AI需求
javascript·产品经理·产品
why技术10 小时前
AI Coding开始进入第四个时代,我还没上车呢!
前端·人工智能·后端
大家的林语冰11 小时前
CSS 已死?DOM 性能黑洞!Pretext 排版革命让你在文本间跳舞,没有 DOM 也能纵享丝滑~
前端·javascript·css
vipbic11 小时前
我也该升级了,陪伴了我7年的博客
前端