用JavaScript讲透面向对象:从“黄同学”介绍到代理模式送花

307 阅读4分钟

用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);  // 调用小美实际的接收方法 
    } 
}; 

这里,xiaomeixiaohong都实现了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写点什么时,不妨先想想:“如果这是现实中的一个场景,我会怎么描述它?”——答案,可能就藏在你的对象属性里,在你的方法逻辑里,甚至在你的代理模式里。