用JavaScript讲透面向对象:从“黄同学”介绍到代理模式送花
引言:JS的“灵活”,是理解世界的钥匙
“JavaScript是弱类型、动态、灵活的脚本语言,前端后端都能运行。”这是多数人对JS的第一印象。但在我看来,JS的“灵活”远不止语法特性——它更像一把“建模现实世界的瑞士军刀”:用“对象”抽象万物,用“方法”模拟动作,甚至能用“代理模式”复刻生活中的人情往来。
作为一名“JS生活建模师”,我的工作不是写复杂的框架或优化性能,而是用JS的语法规则,把现实中的人、事、关系“翻译”成代码。今天,我们就从“介绍黄同学”开始,用JS的面向对象思想,拆解“小彭送花给小美”的故事,最后用“代理模式”让代码更贴近真实世界的逻辑。
一、用JS介绍“黄同学”:从变量到对象的建模
1. 用变量“认识”一个人:简单类型的局限
假设我们要在JS里介绍“黄同学”,最直接的方式是用变量存储信息:
// 简单数据类型:用字符串和数字描述基础信息
const hxtName = "黄同学"; // 姓名(String类型)
const hxtAge = 21; // 年龄(Number类型)
但这种方式的问题很明显:信息是离散的,无法体现“黄同学”是一个“整体”。如果要描述他的“爱好”“职业”,甚至“打招呼”的动作,简单类型就不够用了。
2. 用对象“定义”一个人:复杂类型的抽象
JS的“对象(Object)”正是为解决这个问题而生——它能将属性(描述)和方法(动作)封装成一个整体,完美模拟现实中的“事物”。
我们可以这样“创造”黄同学:
// 复杂数据类型:用对象封装属性和方法
const hxt = {
// 属性:描述对象的特征
name: "黄同学",
age: 21,
hobby: ["编程", "看科幻电影"],
// 方法:对象能执行的动作
sayHello: function() {
console.log(`大家好,我是${this.name},今年${this.age}岁,喜欢${this.hobby.join("和")}~`);
}
};
// 调用方法:黄同学打招呼
hxt.sayHello(); // 输出:"大家好,我是黄同学,今年21岁,喜欢编程和看科幻电影~"
这里,hxt对象包含了“属性”(name/age/hobby)和“方法”(sayHello),像极了现实中一个有血有肉的人——这就是JS面向对象的核心:用对象抽象现实事物,用属性和方法描述事物的“是什么”和“能做什么”。
二、JS如何运行:从“脚本”到“全栈”的生命力
理解了JS的“建模能力”,我们再聊聊它的“生命力”——为什么这门“脚本语言”能从浏览器走向后端,成为全栈开发的首选?
1. 脚本语言的“轻量”:无需编译,即写即跑
与C++等编译型语言(.cpp → .o(二进制)→ 执行文件)不同,JS是脚本语言,无需提前编译。你只需新建一个1.js文件,输入代码后运行node 1.js(后端)或在HTML中用<script>标签引入(前端),就能直接执行。
比如在后端,用Node.js运行“黄同学打招呼”的代码:
node 1.js # 输出:"大家好,我是黄同学..."
在前端,将代码写进HTML的<script>标签:
<!DOCTYPE html> <!-- HTML5标准头,告诉浏览器这是HTML文档 -->
<html>
<body>
<script>
const hxt = { /* ...对象定义... */ };
hxt.sayHello(); // 浏览器控制台输出打招呼信息
</script>
</body>
</html>
这种“即写即跑”的特性,让JS成为快速验证创意的最佳选择——无论是开发一个前端小工具,还是搭一个后端API,都能快速落地。
2. 全场景覆盖:前端的“交互灵魂”与后端的“高效助手”
- 前端:JS是浏览器的“交互灵魂”。从改变页面颜色(
document.body.style.backgroundColor)到实现滑动手势(如“左滑不喜欢”),JS能直接操作HTML文档(Document对象),让页面“活起来”。 - 后端:Node.js的出现让JS突破浏览器限制。通过
fs模块操作文件、http模块搭建服务器,JS能像Python/Java一样处理后端逻辑,甚至凭借“单线程+事件循环”的特性,在高并发场景中表现优异。
这种“前后端通吃”的能力,让JS成为“全栈开发者的必备工具”——而这一切,都源于它“灵活、动态”的语言特性。
三、代理模式:用JS复刻“小彭送花”的人情世故
回到现实场景:小彭想送花给小美,但不好意思直接开口,于是请老乡兼闺蜜小红帮忙转交。如何用JS的面向对象思想,模拟这个“送花”过程?这就需要用到设计模式中的“代理模式”。
1. 现实场景的抽象:对象、属性与方法
首先,我们需要定义“人”的对象模型。每个人(小美、小红、小彭)都有“接收花”的方法(receiverFlower),这是他们的“接口”(即约定的行为)。
// 定义“接收者”接口(用对象方法模拟)
const xiaomei = {
name: "小美",
receiverFlower: function(flower) {
console.log(`${this.name}收到了${flower},脸红红的~`);
}
};
const xiaohong = {
name: "小红",
receiverFlower: function(flower) {
// 小红作为代理,可能先帮小美“检查”花是否新鲜
console.log(`${this.name}帮${xiaomei.name}接收${flower},先闻了闻:“挺香的,转交!”`);
xiaomei.receiverFlower(flower); // 调用小美实际的接收方法
}
};
这里,xiaomei和xiaohong都实现了receiverFlower方法(接口统一),但内部逻辑不同:小美是“实际接收者”,小红是“代理接收者”。
2. 代理模式的核心:接口统一,逻辑解耦
小彭送花时,只需调用代理对象(小红)的receiverFlower方法,无需关心小美是否在场或如何处理花:
const xiaopeng = {
name: "小彭",
sendFlower: function(receiver, flower) {
console.log(`${this.name}让${receiver.name}转交${flower}~`);
receiver.receiverFlower(flower); // 调用接收者的接口方法
}
};
// 小彭通过小红送花给小美
xiaopeng.sendFlower(xiaohong, "玫瑰");
输出结果:
小彭让小红转交玫瑰~
小红帮小美接收玫瑰,先闻了闻:“挺香的,转交!”
小美收到了玫瑰,脸红红的~
这就是代理模式的魅力:
- 接口统一:小红和小美有相同的
receiverFlower方法,小彭无需修改代码就能替换代理(比如换另一个闺蜜); - 逻辑解耦:代理可以添加额外逻辑(如检查花的新鲜度),而小美只需专注“接收”的核心行为;
- 灵活扩展:未来如果需要“匿名送花”,只需修改代理的
receiverFlower方法,无需改动小美或小彭的代码。
这种“像现实一样灵活”的设计,正是JS面向对象思想的高级体现——它不仅能建模事物,还能建模事物之间的关系。
四、总结:JS的本质是“用代码讲好现实的故事”
从“介绍黄同学”的基础对象,到“小彭送花”的代理模式,JS的魅力从未局限于“写代码”,而是“用代码讲好现实的故事”。它的“弱类型”“动态”“灵活”,本质上是为了更贴近人类的思维方式——我们描述一个人时,不会先想“他是字符串还是数字”,而是关注“他的名字、年龄、爱好”;我们转交礼物时,不会纠结“接口是否匹配”,而是找一个“信得过的中间人”。
作为“JS生活建模师”,我的工作就是用这门语言,把现实中的人、事、关系翻译成代码。因为我始终相信:最好的代码,不是“技术有多复杂”,而是“能否让不懂代码的人,也能看懂它讲的故事”。
下一次,当你想用JS写点什么时,不妨先想想:“如果这是现实中的一个场景,我会怎么描述它?”——答案,可能就藏在你的对象属性里,在你的方法逻辑里,甚至在你的代理模式里。