从生活场景学透 JavaScript 原型与原型链

一、构造函数:以 "人" 为例的对象工厂

1. 生活场景下的构造函数定义

我们以 "人" 为场景创建构造函数,每个人都有姓名、年龄等个性化属性,也有人类共有的特征:

javascript 复制代码
// 人类构造函数
function Person(name, age) {
  this.name = name;
  this.age = age;
  // 每个人独特的属性
  this.hobby = `喜欢 ${name}的爱好`;
}

// 创建两个人的实例
const person1 = new Person("小明", 20);
const person2 = new Person("小红", 22);

console.log(person1); // Person { name: '小明', age: 20, hobby: '喜欢小明的爱好' }
console.log(person2); // Person { name: '小红', age: 22, hobby: '喜欢小红的爱好' }

2. 基础数据类型的生活类比

以 "水果" 为例理解基础数据类型的两种定义方式:

javascript 复制代码
// 定义水果的两种方式
let fruit1 = "苹果"; // 字面量方式
let fruit2 = new String("香蕉"); // 构造函数方式

console.log(fruit1); // 苹果
console.log(fruit2); // 香蕉

二、原型(prototype):提取人类共同特征

1. 提取人类共同属性到原型

人类共有的属性(如物种、默认行为)适合放在原型上:

javascript 复制代码
// 优化:将人类共同属性放到原型上
Person.prototype.species = "智人";
Person.prototype.gender = "默认未知";
Person.prototype.speak = function() {
  return `${this.name}说:你好!`;
};

function Person(name, age) {
  this.name = name;
  this.age = age;
  this.hobby = `喜欢 ${name}的爱好`;
}

const person1 = new Person("小明", 20);
const person2 = new Person("小红", 22);

// 访问原型上的属性
console.log(person1.species); // 智人
console.log(person2.speak()); // 小红说:你好!
console.log(person1); // Person { name: '小明', age: 20, hobby: '喜欢小明的爱好' }

2. 原型属性的不可修改性演示

尝试修改原型属性,观察实例的变化:

javascript 复制代码
// 原型属性不可修改的演示
Person.prototype.species = "智人";
Person.prototype.speak = function() {
  return `${this.name}说:你好!`;
};

function Person(name, age) {
  this.name = name;
  this.age = age;
}

const person = new Person("小明", 20);

console.log(person.species); // 智人
// 尝试修改原型属性
person.species = "外星人";
console.log(person.species); // 外星人(实例自身添加了属性)
console.log(Person.prototype.species); // 智人(原型属性未改变)

三、对象原型(proto):隐式链接的生活比喻

1. 隐式原型的链接关系

以 "动物" 为例说明隐式原型的指向关系:

javascript 复制代码
// 动物构造函数
function Animal() {}
Animal.prototype.eat = function() {
  return "正在进食";
};

// 狗构造函数
function Dog(name) {
  this.name = name;
}
// 狗的原型指向动物的原型
Dog.prototype = new Animal();

const dog = new Dog("旺财");

// 验证隐式原型关系
console.log(dog.__proto__ === Dog.prototype); // true
console.log(Dog.prototype.__proto__ === Animal.prototype); // true
console.log(dog.eat()); // 正在进食(通过原型链调用)

2. 隐式原型的查找机制

通过 "学生" 对象演示属性查找过程:

javascript 复制代码
// 学生构造函数
function Student(name) {
  this.name = name;
}

// 学生原型添加属性
Student.prototype.school = "默认学校";
Student.prototype.study = function() {
  return `${this.name}在学习`;
};

const student = new Student("小李");

// 查找属性的过程
console.log(student.name); // 小李(自身属性)
console.log(student.school); // 默认学校(原型属性)
console.log(student.study()); // 小李在学习(原型方法)

四、this 的原理:从 "创建房屋" 理解 new 操作

1. 房屋构造函数中的 this

模拟房屋建造过程,理解 this 在构造函数中的作用:

javascript 复制代码
// 房屋构造函数
function House(owner, area) {
  this.owner = owner;
  this.area = area;
  this.roomCount = 3; // 默认3个房间

  // 这里隐含了new的执行过程
  // 1. 创建空对象 obj = {}
  // 2. this指向obj
  // 3. 执行属性赋值
  // 4. obj.__proto__ = House.prototype
  // 5. 返回obj
}

House.prototype.address = "未知地址";
House.prototype.showInfo = function() {
  return `${this.owner}的房子,面积 ${this.area}㎡,位于 ${this.address}`;
};

const myHouse = new House("张三", 120);
console.log(myHouse.showInfo()); // 张三的房子,面积120㎡,位于未知地址

五、原型链:从 "交通工具" 看对象继承关系

1. 交通工具的原型链结构

通过交通工具的层级关系展示原型链:

javascript 复制代码
// 交通工具基类
function Vehicle() {
  this.type = "交通工具";
}
Vehicle.prototype.move = function() {
  return "正在移动";
};

// 汽车类
function Car(brand) {
  this.brand = brand;
}
Car.prototype = new Vehicle();
Car.prototype.drive = function() {
  return `${this.brand}汽车在行驶`;
};

// 电动车类
function ElectricCar(brand, battery) {
  Car.call(this, brand);
  this.battery = battery;
}
ElectricCar.prototype = new Car("默认品牌");
ElectricCar.prototype.charge = function() {
  return `正在给 ${this.brand}电动车充电`;
};

// 创建电动车实例
const car = new ElectricCar("特斯拉", "锂电池");

// 原型链查找演示
console.log(car.brand); // 特斯拉(自身属性)
console.log(car.drive()); // 特斯拉汽车在行驶(Car原型方法)
console.log(car.move()); // 正在移动(Vehicle原型方法)
console.log(car.charge()); // 正在给特斯拉电动车充电(自身方法)

2. 原型链的根对象演示

通过 Object.create 创建特殊对象:

javascript 复制代码
// 普通对象
const normalObj = new Object();
console.log(normalObj.__proto__); // Object.prototype

// 使用Object.create创建无原型的对象
const specialObj = Object.create(null);
console.log(specialObj.__proto__); // undefined

// 验证原型链终点
console.log(Object.prototype.__proto__); // null

六、生活场景总结表

概念 生活类比 代码
构造函数 工厂生产线 首字母大写,用 new 创建实例
原型 (prototype) 人类共同特征手册 存放同类对象的公共属性和方法
隐式原型 (proto) 家族族谱 实例指向构造函数的原型
原型链 生物进化树 多层继承关系形成的属性查找链路
this 工厂中的施工图纸 指向新创建的对象实例
相关推荐
随风一样自由5 小时前
【前端独角兽】刚进入前端领域的前端开发用jQuery还是Vue3?
前端·javascript·vue3·jquery
IMPYLH6 小时前
HTML 的 <data> 元素
前端·html
YHHLAI6 小时前
[特殊字符] 面试中的 Promise —— 从入门到精通
前端·javascript·面试
weixin_BYSJ19877 小时前
SpringBoot + MySQL 乒乓球运动员信息管理系统项目实战--附源码04954
java·javascript·spring boot·python·django·flask·php
沪飘大军7 小时前
ll-llm:一个零依赖、可插拔的 OpenAI 兼容 LLM 代理
javascript
kyriewen8 小时前
我扒了 GPT-5.6 的全部编程跑分——有一项 OpenAI 没敢放出来
前端·gpt·ai编程
前端H9 小时前
微前端 v3 架构升级:从加载隔离到状态协同
前端·架构·状态模式
山河木马9 小时前
GPU自动处理专题3-NDC怎么映射成屏幕像素坐标(视口变换)
javascript·webgl·图形学
陆枫Larry10 小时前
小程序包体积优化:用 SVG 图片替换 iconfont,并保留 CSS 控色能力
前端
Appthing10 小时前
在 TanStack Start 中使用 VitePWA 的正确配置
javascript