当前位置: 首页 > news >正文

ts与面向对象

刚学前端那会儿,我总被 “面向对象编程” 这个词搞得头大,感觉它特别高深莫测。后来我发现,其实它就像我们整理房间一样,把相似的东西归类,用起来更方便。

一、面向对象是啥?先从生活找灵感​

想象一下,你有一柜子衣服,T 恤、牛仔裤、外套堆在一起,找件衣服得翻半天。但如果你把 T 恤放一个抽屉,裤子放另一个,外套单独挂起来,是不是找起来快多了?这就是面向对象的核心理念 —— 把相似的东西归类成 “对象”,每个对象有自己的 “属性” 和 “行为”。​
在前端里,一个按钮可以是一个对象,它有颜色、大小这些属性,还有点击后跳转页面这种行为;一个用户信息框也是对象,属性包括用户名、头像,行为可能是修改密码、退出登录。​

二、对象的基础:属性和方法​

用 TypeScript 创建一个简单的 “人” 对象,看看属性和方法怎么玩,这里我们给属性和方法都加上类型注解:​

// 创建一个“人”对象​
const person: { name: string; age: number; sayHello: () => void } = {​name: "蔡徐坤", // 属性:名字​age: 25, // 属性:年龄​sayHello: function() { // 方法:打招呼​console.log("大家好,我是练习时长2年半的个人练习生" + this.name);}};​
​
// 调用对象的方法​
person.sayHello();


在这个例子里,name和age是对象person的属性,就像人的名字和年龄;sayHello是方法,是person能做的事情。这里this指的就是当前对象person,如果在其他函数里乱用this会出大问题,后面咱们会细说。​

三、构造函数

要是有很多人,一个个创建对象太麻烦了,这时候构造函数就派上用场,它就像工厂的流水线,能批量生产相似的对象。在 TypeScript 中,我们这样定义构造函数:​

// 定义一个“人”的构造函数​
class Person {​name: string;​age: number;constructor(name: string, age: number) {this.name = name;this.age = age;}sayHello(): void {​console.log("大家好,我是练习时长2年半的个人练习生" + this.name);}}​
​
// 用构造函数创建两个“人”对象​
const person1 = new Person("小蔡", 22);const person2 = new Person("小坤", 28);​
​
person1.sayHello();​
person2.sayHello();


这里Person就是构造函数(在 TypeScript 用类的形式定义),用new关键字就能创建新对象。每个新对象都有自己独立的name、age属性和sayHello方法,就像不同的人都有自己的名字、年龄,都能打招呼。​
不过构造函数有个小问题,每个对象的sayHello方法虽然代码一样,但在内存里是分开存的,浪费空间。这时候就需要原型来优化了。​

四、原型

原型就像对象的公共图书馆,所有同类型对象都能共享里面的 “技能”。还是以 “人” 为例,在 TypeScript 中利用原型的方式如下:​

class Person {​name: string;​age: number;constructor(name: string, age: number) {this.name = name;this.age = age;}}​
​
// 把sayHello方法放到原型上​
Person.prototype.sayHello = function(): void {​console.log("大家好,我是练习时长2年半的个人练习生" + this.name);};​
​
const person1 = new Person("小蔡", 23);const person2 = new Person("小坤", 26);​
​
person1.sayHello();​
person2.sayHello();


现在sayHello方法存在Person的原型里,person1和person2不用各自复制一份,节省了内存。当调用person1.sayHello()时,TypeScript 会先在person1对象里找sayHello,找不到就去原型里找,找到就执行。​

五、类:更简洁的语法糖​

在 TypeScript 中,类的语法更加完善,它不仅是语法糖,还能利用类型系统让代码更健壮。还是以 “人” 为例:​

class Person {constructor(public name: string, public age: number) {}sayHello(): void {​console.log("大家好,我是练习时长2年半的个人练习生" + this.name);}}​
​
const person1 = new Person("小蔡", 24);const person2 = new Person("小坤", 27);​
​
person1.sayHello();​
person2.sayHello();


这里在constructor参数前面加上public,会自动创建同名的公有属性,比 JavaScript 写法更简洁。sayHello方法直接写在类里面,类型明确,代码结构也更清晰。​

六、实际应用场景

比如做一个简单的图片轮播效果,把整个轮播组件当成一个对象,在 TypeScript 中实现如下:​

<!DOCTYPE html><html lang="en">​
​
<head><meta charset="UTF-8"><title>图片轮播</title></head>​
​
<body><div id="slider"><img src="img1.jpg" alt="图片1"><img src="img2.jpg" alt="图片2"><img src="img3.jpg" alt="图片3"></div><script>class ImageSlider {​slider: HTMLElement;​images: NodeListOf<HTMLImageElement>;​currentIndex: number;constructor(sliderId: string) {const element = document.getElementById(sliderId);if (!element) {throw new Error(`找不到id为 ${sliderId} 的元素`);}this.slider = element;this.images = this.slider.getElementsByTagName('img');this.currentIndex = 0;this.showImage();}showImage(): void {for (let i = 0; i < this.images.length; i++) {this.images[i].style.display = 'none';}this.images[this.currentIndex].style.display = 'block';}nextImage(): void {this.currentIndex = (this.currentIndex + 1) % this.images.length;this.showImage();}}​
​const slider = new ImageSlider('slider');// 模拟点击下一张图片​setInterval(() => {​slider.nextImage();}, 3000);</script></body>​
​
</html>



在这个ImageSlider类里,constructor初始化轮播组件,我们添加了更严格的类型检查,比如确保获取到正确的 DOM 元素,否则抛出错误。showImage方法负责显示当前图片,nextImage方法切换到下一张图片。把整个轮播逻辑封装成一个对象,借助 TypeScript 的类型系统,代码结构更清晰,维护起来也更方便,还能减少很多运行时的错误。​

七、面向对象的坑:this的陷阱​

this在面向对象编程里特别容易搞混。在 TypeScript 中,this的值同样取决于函数的调用方式:​
作为对象的方法调用,this指向这个对象,比如person.sayHello()里this就是person。​
直接调用函数,this在非严格模式下指向全局对象(浏览器里是window),在严格模式下是undefined。​

function test(): void {​console.log(this);}test(); // 在浏览器里会打印window​
​
用call、apply、bind调用函数,可以手动指定this的值:​
​
class Person {​name: string;constructor(name: string) {this.name = name;}sayHi(): void {​console.log("嗨,我是练习时长2年半的个人练习生" + this.name);}}​
​
const person = new Person("蔡徐坤");const anotherPerson = { name: "爱坤" };​
​
person.sayHi.call(anotherPerson); // 打印:嗨,我是爱坤​

八、总结

通过这些例子可以看出,面向对象编程能把复杂的代码拆分成一个个独立的对象,每个对象负责自己的事情,就像分工明确的团队。它的好处有:​
代码复用:一个对象的方法和属性可以在其他地方重复使用,不用重复写代码。​
结构清晰:对象之间职责分明,改代码或者加功能时,很容易找到对应的地方。​
可维护性强:出了问题可以快速定位到某个对象,修改也不会影响其他部分。​
类型安全(TypeScript 特有的优势):提前发现很多类型错误,让代码更健壮。​
但也不是所有场景都适合用面向对象,比如一些简单的页面效果,用面向过程的编程方式可能更简单直接。一般在开发大型项目、复杂交互组件时,面向对象的优势就能充分发挥出来。

相关文章:

  • trivy开源安全漏洞扫描器——筑梦之路
  • 操作系统:进程是一个非常重要的抽象概念
  • QML 样式库
  • PySide6 GUI 学习笔记——常用类及控件使用方法(常用类尺寸QSizeF)
  • Java发生OOM是否必然导致JVM退出
  • 【工具变量】A股上市企业数据资产披露水平数据集(2000-2023年)
  • 8.QT-按钮类控件|Push Button|Radio Button|Check Box|Tool Button(C++)
  • 提交bug单时,应该说明哪些信息?
  • 强制重装及验证onnxruntime-gpu是否正确工作
  • 借助 OpenCV 和 PyTorch 库,利用卷积神经网络提取图像边缘特征
  • C++项目 —— 基于多设计模式下的同步异步日志系统(4)(双缓冲区异步任务处理器(AsyncLooper)设计)
  • HTTP 2.0 和 3.0 的区别
  • DSN主从同步
  • Linux系统中iptables防火墙
  • 松灵Cobot Magic双臂具身遥操机器人(基于ROS的定位建图与协同导航技术)
  • DeepSeek 即将联合 vLLM 开源推理引擎
  • AI-Sphere-Butler之如何使用Llama factory LoRA微调Qwen2-1.5B/3B专属管家大模型
  • C++ 俄罗斯方块 | Tetris⚡YQW · Studio ⚡【无需下载图片】
  • 铅酸电池充电器方案EG1253+EG4321
  • JVM 学习
  • 宁德时代与广汽等五车企发布10款巧克力换电新车型:年内将将完成30城1000站计划
  • 印控克什米尔发生恐袭事件,外交部:中方反对一切形式的恐怖主义
  • 职工疗休养如何告别千篇一律?安徽含山给出新解法
  • 吉林省委原书记、吉林省人大常委会原主任何竹康逝世
  • 北京地铁5号线仗义执言女乘客发文:同理心无比重要,希望就此平息
  • 电商平台全面取消“仅退款”:电商反内卷一大步,行业回归良性竞争