从生活场景学透 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 工厂中的施工图纸 指向新创建的对象实例
相关推荐
前端W1 分钟前
腾讯地图组件使用说明文档
前端
页面魔术3 分钟前
无虚拟dom怎么又流行起来了?
前端·javascript·vue.js
胡gh4 分钟前
如何聊懒加载,只说个懒可不行
前端·react.js·面试
Double__King7 分钟前
巧用 CSS 伪元素,让背景图自适应保持比例
前端
Mapmost8 分钟前
【BIM+GIS】BIM数据格式解析&与数字孪生适配的关键挑战
前端·vue.js·three.js
一涯9 分钟前
写一个Chrome插件
前端·chrome
鹧鸪yy16 分钟前
认识Node.js及其与 Nginx 前端项目区别
前端·nginx·node.js
跟橙姐学代码17 分钟前
学Python必须迈过的一道坎:类和对象到底是什么鬼?
前端·python
汪子熙19 分钟前
浏览器里出现 .angular/cache/19.2.6/abap_test/vite/deps 路径究竟说明了什么
前端·javascript·面试