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

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

构造函数(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'
相关推荐
Crystal3281 小时前
Git 基础:生成版本、撤消操作、版本重置、忽略文件
前端·git·github
lichenyang4531 小时前
React 组件通讯全案例解析:从 Context 到 Ref 的实战应用
前端
国服第二切图仔1 小时前
Electron for 鸿蒙pc项目实战之右键菜单组件
javascript·electron·harmonyos·鸿蒙pc
姓王者1 小时前
chen-er 专为Chen式ER图打造的npm包
前端·javascript
青莲8431 小时前
Android Jetpack - 2 ViewModel
android·前端
崽崽的谷雨1 小时前
react里ag-grid实现树形数据展示
前端·react.js·前端框架
栀秋6661 小时前
就地编辑功能开发指南:从代码到体验的优雅蜕变
前端·javascript·代码规范
国服第二切图仔1 小时前
Electron for 鸿蒙PC项目实战案例 - 连连看小游戏
前端·javascript·electron·鸿蒙pc