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

第五节:对象与原型链:JavaScript 的“类”与“继承”

📌 第五节:对象与原型链:JavaScript 的“类”与“继承”

目标:理解对象创建、原型继承、this 绑定,掌握类语法与原型设计模式,实现模块化组件开发。


一、对象基础:数据的“容器”

1. 对象字面量与属性访问
  • 语法:

    const person = {name: "Alice",age: 30,greet() { // 方法简写console.log(`Hi, I'm ${this.name}!`);},[Symbol("id")]: "unique-123", // Symbol 属性
    };
    
  • 访问方式:

    console.log(person.name); // "Alice"(点语法)
    console.log(person["age"]); // 30(方括号语法,可动态访问)
    
2. 对象操作
  • 添加/修改属性:

    person.job = "Engineer"; // 动态添加属性
    person.age = 31; // 修改属性
    
  • 删除属性:

    javascriptdelete person.job; // 删除属性
    
  • 遍历属性:

    for (const key in person) {if (person.hasOwnProperty(key)) { // 排除继承属性console.log(`${key}: ${person[key]}`);}
    }
    
3. 对象拷贝
  • 浅拷贝:

    const shallowCopy = { ...person }; // 展开运算符
    // 或 Object.assign({}, person);
    
  • 深拷贝:

    const deepCopy = JSON.parse(JSON.stringify(person)); // 仅适用于简单对象
    // 或使用 Lodash 的 `_.cloneDeep`
    

二、原型链:继承的“幕后英雄”

1. 原型与构造函数
  • __proto__prototype

    • 每个对象有 __proto__ 指向其原型(隐式原型)。
    • 函数有 prototype 属性,指向其构造的实例的原型。
    function Person(name) {this.name = name;
    }
    Person.prototype.greet = function() {console.log(`Hello, I'm ${this.name}!`);
    };const alice = new Person("Alice");
    console.log(alice.__proto__ === Person.prototype); // true
    alice.greet(); // 输出:Hello, I'm Alice!
    
2. 原型链查找规则
  • 查找顺序:对象自身属性 → 原型 → 原型链向上查找,直到null

    console.log(alice.toString()); // 调用 Object.prototype.toString
    console.log(alice.__proto__.__proto__ === Object.prototype); // true
    
3. 修改原型链
  • 动态添加原型方法:

    Person.prototype.sayAge = function() {console.log(`I'm ${this.age} years old.`);
    };
    alice.age = 30;
    alice.sayAge(); // 输出:I'm 30 years old.
    
  • 原型链陷阱:

    • 共享引用类型属性可能导致意外修改。
    function Animal() {this.foods = []; // 共享引用类型
    }
    const cat = new Animal();
    const dog = new Animal();
    cat.foods.push("fish");
    console.log(dog.foods); // ["fish"](意外共享)
    

三、this 绑定:上下文的“指挥官”

1. this 的四种绑定规则
规则示例this 指向
默认绑定function foo() { console.log(this); }全局对象(严格模式为 undefined
隐式绑定obj.method()调用对象(obj
显式绑定foo.call(obj)foo.apply(obj)指定对象(obj
new 绑定new Foo()新创建的实例对象
2. 绑定优先级
  • 显式绑定 > new 绑定 > 隐式绑定 > 默认绑定

  • 箭头函数:继承外层作用域的this,无动态绑定。

    const obj = {name: "Bob",greet: () => console.log(`Hello, ${this.name}`), // this 为外层作用域(可能是 window/undefined)normalGreet() {console.log(`Hello, ${this.name}`); // this 为 obj},
    };
    obj.greet(); // 输出:Hello, undefined(箭头函数无自身 this)
    obj.normalGreet(); // 输出:Hello, Bob
    
3. 常见问题与解决方案
  • 回调函数中的 this 丢失:

    const button = {text: "Click me",handleClick() {console.log(`Button clicked: ${this.text}`);},
    };
    document.querySelector("button").onclick = button.handleClick; // this 丢失,指向 button 元素
    

    解决方案:

    • 使用箭头函数包裹:

      document.querySelector("button").onclick = () => button.handleClick();
      
    • 或显式绑定:

      document.querySelector("button").onclick = button.handleClick.bind(button);
      

四、类语法:ES6 的“语法糖”

1. 类定义与继承
  • 基础类:

    class Person {constructor(name, age) {this.name = name;this.age = age;}greet() {console.log(`Hi, I'm ${this.name}!`);}
    }
    const bob = new Person("Bob", 25);
    bob.greet(); // 输出:Hi, I'm Bob!
    
  • 继承:

    class Student extends Person {constructor(name, age, major) {super(name, age); // 调用父类构造函数this.major = major;}study() {console.log(`${this.name} is studying ${this.major}.`);}
    }
    const charlie = new Student("Charlie", 20, "Math");
    charlie.greet(); // 输出:Hi, I'm Charlie!
    charlie.study(); // 输出:Charlie is studying Math.
    
2. 类方法与静态方法
  • 实例方法:

    class Dog {bark() {console.log("Woof!");}
    }
    
  • 静态方法(直接通过类调用):

    class MathUtils {static add(a, b) {return a + b;}
    }
    console.log(MathUtils.add(2, 3)); // 5
    
3. Getter 与 Setter
  • 控制属性访问:

    class Circle {constructor(radius) {this._radius = radius; // 约定前缀 `_` 表示内部属性}get radius() {return this._radius;}set radius(newRadius) {if (newRadius > 0) {this._radius = newRadius;} else {console.error("Radius must be positive!");}}
    }
    const circle = new Circle(5);
    console.log(circle.radius); // 5
    circle.radius = 10; // 调用 setter
    circle.radius = -1; // 输出错误信息
    

五、实战案例:图书管理系统

目标:实现一个图书类,支持添加、删除、搜索图书,并统计库存。
代码实现
// 1. 定义图书类
class Book {constructor(title, author, quantity) {this.title = title;this.author = author;this.quantity = quantity;}updateQuantity(delta) {this.quantity += delta;if (this.quantity < 0) {console.error("库存不足!");this.quantity = 0;}}
}// 2. 定义书店类(继承)
class Bookstore {constructor() {this.books = [];}addBook(book) {this.books.push(book);}removeBook(title) {this.books = this.books.filter((book) => book.title !== title);}searchByAuthor(author) {return this.books.filter((book) => book.author === author);}getTotalInventory() {return this.books.reduce((sum, book) => sum + book.quantity, 0);}
}// 3. 使用示例
const jsBook = new Book("JavaScript Guide", "Alice", 10);
const pythonBook = new Book("Python Basics", "Bob", 5);
const store = new Bookstore();
store.addBook(jsBook);
store.addBook(pythonBook);
jsBook.updateQuantity(-3); // 减少库存
console.log(store.getTotalInventory()); // 输出:12
console.log(store.searchByAuthor("Alice")); // 输出:[{ title: "JavaScript Guide", ... }]

六、常见问题与最佳实践

1. 原型继承 vs 类继承
特性原型继承类继承(ES6)
语法显式操作原型链声明式语法,更接近传统 OOP
可读性较低(需理解原型链)更高(语法糖)
适用场景底层原理学习、性能优化现代项目开发
2. 避免滥用继承
  • 组合优于继承:优先使用对象组合而非深度继承。

    // 组合示例:通过属性引入功能
    const loggerMixin = {log() {console.log(`${this.name}: Action performed`);},
    };
    class User {constructor(name) {this.name = name;}
    }
    Object.assign(User.prototype, loggerMixin); // 组合功能
    
3. 性能优化
  • 缓存原型方法

    :减少频繁查找原型链。

    const hasOwnProperty = Object.prototype.hasOwnProperty;
    function isProperty(obj, key) {return hasOwnProperty.call(obj, key); // 避免在循环中重复查找
    }
    

七、课后任务

基础任务
  1. 创建一个 Animal 类,支持 eatsleep 方法,并继承一个 Dog 子类。
  2. 用类语法实现一个“银行账户”模块,支持存款、取款、查询余额。
  3. 封装一个“防篡改”对象,禁止修改或删除属性(使用 Object.freeze 或 Proxy)。
进阶任务
  1. 设计一个“任务队列”类,支持并发控制(限制同时执行的任务数)。
  2. 实现一个“观察者模式”类,支持多个监听器订阅和通知。
  3. 用 Proxy 实现一个“数据验证”类,拦截对象的属性设置操作。

📌 关键点总结

  1. 对象基础:
    • 掌握对象字面量、属性访问、拷贝与遍历。
  2. 原型链与继承:
    • 理解 __proto__prototype、原型链查找规则,避免原型链陷阱。
  3. this 绑定:
    • 区分四种绑定规则,优先使用箭头函数或显式绑定。
  4. 类语法:
    • 熟练定义类、继承、静态方法、Getter/Setter,区分类继承与组合。

🎯 下一节预告

「异步编程:从回调地狱到 Async/Await」

  • 破解回调地狱,掌握 Promise、async/await,实现一个“天气查询”应用。

如果需要补充更多案例(如设计模式应用、Object.create 手动实现继承、Proxy 高级用法等),或调整内容深度,请随时告知! 😊

相关文章:

第五节:对象与原型链:JavaScript 的“类”与“继承”

&#x1f4cc; 第五节&#xff1a;对象与原型链&#xff1a;JavaScript 的“类”与“继承” 目标&#xff1a;理解对象创建、原型继承、this 绑定&#xff0c;掌握类语法与原型设计模式&#xff0c;实现模块化组件开发。 一、对象基础&#xff1a;数据的“容器” 1. 对象字面…...

本地的ip实现https访问-OpenSSL安装+ssl正式的生成(Windows 系统)

1.下载OpenSSL软件 网站地址&#xff1a;Win32/Win64 OpenSSL Installer for Windows - Shining Light Productions 安装: 一直点击下一步就可以了 2.设置环境变量 在开始菜单右键「此电脑」→「属性」→「高级系统设置」→「环境变量」 在Path 中添加一个: xxxx\OpenSSL-…...

Spring Boot + MyBatis-Plus 高并发读写分离实战

引言 在高并发场景下&#xff0c;单一数据库实例往往成为性能瓶颈。数据库读写分离通过将读操作和写操作分配到不同的数据库实例&#xff0c;有效缓解主库压力&#xff0c;提升系统吞吐量。MyBatis-Plus 作为一款强大的持久层框架&#xff0c;结合 Spring Boot 能够轻松实现读…...

HarmonyOS 【诗韵悠然】AI古诗词赏析APP开发实战从零到一系列(二、项目准备与后台服务搭建)

在开发一款面向HarmonyOS平台的应用程序——【诗韵悠然】AI古诗词赏析APP时&#xff0c;选择了流行Go语言作为后端开发语言&#xff0c;并使用了go-zero微服务框架来搭建服务接口。本文将详细介绍项目准备和后台服务搭建的过程&#xff0c;帮助大家更好地理解和掌握go-zero框架…...

【PmHub后端篇】PmHub中基于自定义注解和AOP的服务接口鉴权与内部认证实现

1 引言 在现代软件开发中&#xff0c;尤其是在微服务架构下&#xff0c;服务接口的鉴权和内部认证是保障系统安全的重要环节。本文将详细介绍PmHub中如何利用自定义注解和AOP&#xff08;面向切面编程&#xff09;实现服务接口的鉴权和内部认证&#xff0c;所涉及的技术知识点…...

多模态AI新纪元:Vertex AI Gemini与Spring AI深度集成实践

企业级AI集成进阶&#xff1a;Spring AI与Vertex AI Gemini的配置与调优实战 一、前沿技术&#xff1a;多模态模型的企业级配置范式 在生成式AI技术快速迭代的当下&#xff0c;企业级应用对模型配置的精细化需求日益增长。Vertex AI Gemini作为Google推出的多模态大模型&…...

大语言模型RLHF训练框架全景解析:OpenRLHF、verl、LLaMA-Factory与SWIFT深度对比

引言 随着大语言模型&#xff08;LLM&#xff09;参数规模突破千亿级&#xff0c;基于人类反馈的强化学习&#xff08;RLHF&#xff09;成为提升模型对齐能力的关键技术。OpenRLHF、verl、LLaMA-Factory和SWIFT作为开源社区的四大标杆框架&#xff0c;分别通过分布式架构、混合…...

开源AI数字人分身克隆小程序源码系统深度剖析:从搭建到应用

在人工智能与小程序生态深度融合的当下&#xff0c;开源 AI 数字人分身克隆小程序源码成为开发者的热门工具。从搭建基础环境到实现实际应用&#xff0c;这一过程涉及多项技术与复杂流程。本文将带您深入剖析开源 AI 数字人分身克隆小程序源码&#xff0c;揭开其从搭建到应用的…...

ETL背景介绍_1:数据孤岛仓库的介绍

1 ETL介绍 1.1 数据孤岛 随着企业内客户数据大量的涌现&#xff0c;单个数据库已不再足够。为了储存这些数据&#xff0c;公司通常会建立多个业务部门组织的数据库来保存数据。比如&#xff0c;随着数据量的增长&#xff0c;公司通常可能会构建数十个独立运行的业务数据库&am…...

Linux系统:虚拟文件系统与文件缓冲区(语言级内核级)

本节重点 初步理解一切皆文件理解文件缓冲区的分类用户级文件缓冲区与内核级文件缓冲区用户级文件缓冲区的刷新机制两级缓冲区的分层协作 一、虚拟文件系统 1.1 理解“一切皆文件” 我们都知道操作系统访问不同的外部设备&#xff08;显示器、磁盘、键盘、鼠标、网卡&#…...

智能体的典型应用:自动驾驶、智能客服、智能制造、游戏AI与数字人技术

本文为《React Agent&#xff1a;从零开始构建 AI 智能体》专栏系列文章。 专栏地址&#xff1a;https://blog.csdn.net/suiyingy/category_12933485.html。项目地址&#xff1a;https://gitee.com/fgai/react-agent&#xff08;含完整代码示​例与实战源&#xff09;。完整介绍…...

【技巧】使用UV创建python项目的开发环境

回到目录 【技巧】使用UV创建python项目的开发环境 0. 为什么用UV 下载速度快、虚拟环境、多版本python支持、清晰的依赖关系 1. 安装基础软件 1.1. 安装python 下载地址&#xff1a;https://www.python.org/downloads/windows/ 1.2. 安装UV > pip install uv -i ht…...

什么是时序数据库?

2025年5月13日&#xff0c;周二清晨 时序数据库&#xff08;Time Series Database&#xff0c;TSDB&#xff09;是一种专门用于高效存储、管理和分析时间序列数据的数据库系统。时间序列数据是指按时间顺序记录的数据点&#xff0c;通常包含时间戳和对应的数值或事件&#xff0…...

react父组件往孙子组件传值Context API

步骤&#xff1a; 创建一个 Context 在父组件中用 Provider 提供值 在孙子组件中用 useContext 消费值 // 创建 Context const MyContext React.createContext();// 父组件 const Parent () > {const value "Hello from parent";return (<MyContext.Provid…...

2025年第十六届蓝桥杯大赛软件赛C/C++大学B组题解

第十六届蓝桥杯大赛软件赛C/C大学B组题解 试题A: 移动距离 问题描述 小明初始在二维平面的原点&#xff0c;他想前往坐标(233,666)。在移动过程中&#xff0c;他只能采用以下两种移动方式&#xff0c;并且这两种移动方式可以交替、不限次数地使用&#xff1a; 水平向右移动…...

国联股份卫多多与七腾机器人签署战略合作协议

5月13日&#xff0c;七腾机器人有限公司&#xff08;以下简称“七腾机器人”&#xff09;市场部总经理孙永刚、销售经理吕娟一行到访国联股份卫多多&#xff0c;同卫多多/纸多多副总裁、产发部总经理段任飞&#xff0c;卫多多机器人产业链总经理郭碧波展开深入交流&#xff0c;…...

python学习笔记七(文件)

文章目录 Python 文件操作与异常处理全面指南一、文件基本知识1. 文件类型2. 文件操作基本步骤 二、文件操作1. 打开文件2. 读取文件内容3. 写入文件4. 关闭文件5. 使用with语句&#xff08;推荐&#xff09; 三、CSV文件操作1. 使用csv模块2. 读取CSV文件3. 写入CSV文件 四、异…...

WebGL 开发的前沿探索:开启 3D 网页的新时代

你是否曾好奇&#xff0c;为何如今网页上能呈现出如同游戏般逼真的 3D 场景&#xff1f;这一切都要归功于 WebGL。它看似神秘&#xff0c;却悄然改变着我们浏览网页的体验。以往&#xff0c;网页内容大多局限于二维平面&#xff0c;可 WebGL 打破了这一限制。它究竟凭借什么&am…...

高防服务器部署实战:从IP隐匿到协议混淆

1. IP隐匿方案设计 传统高防服务器常因源站IP暴露遭针对性攻击&#xff0c;群联通过三层架构实现深度隐藏&#xff1a; 流量入口层&#xff1a;域名解析至动态CNAME节点&#xff08;如ai-protect.example.com&#xff09;。智能调度层&#xff1a;AI模型分配清洗节点&#xf…...

激光雷达定位算法在FPGA中的实现——section3 Matlab实现和校验

1、校验section2的计算方法是否正确 以section1里面的图示 举个例子: 1.1 手动计算...

AI+可视化:数据呈现的未来形态

当AI生成的图表开始自动“美化”数据&#xff0c;当动态可视化报告能像人类一样“讲故事”&#xff0c;当你的眼球运动直接决定数据呈现方式——数据可视化的未来形态&#xff0c;正在撕裂传统认知。某车企用AI生成的3D可视化方案&#xff0c;让设计师集体失业&#xff1b;某医…...

[免费]微信小程序医院预约挂号管理系统(uni-app+SpringBoot后端+Vue管理端)【论文+源码+SQL脚本】

大家好&#xff0c;我是java1234_小锋老师&#xff0c;看到一个不错的微信小程序医院预约挂号管理系统(uni-appSpringBoot后端Vue管理端)&#xff0c;分享下哈。 项目视频演示 【免费】微信小程序医院预约挂号管理系统(uni-appSpringBoot后端Vue管理端) Java毕业设计_哔哩哔哩…...

【网络入侵检测】基于源码分析Suricata的IP分片重组

【作者主页】只道当时是寻常 【专栏介绍】Suricata入侵检测。专注网络、主机安全&#xff0c;欢迎关注与评论。 目录 目录 1.概要 2. 配置信息 2.1 名词介绍 2.2 defrag 配置 3. 代码实现 3.1 配置解析 3.1.1 defrag配置 3.1.2 主机系统策略 3.2 分片重组模块 3.2.1…...

Spring框架请求注解

Spring框架请求注解 1.RequestParam 作用&#xff1a;从请求的 查询参数&#xff08;Query Parameters&#xff09; 或 表单数据&#xff08;Form Data&#xff09; 中提取参数。适用场景&#xff1a; GET 请求的 URL 参数&#xff08;如 /users?nameTom&age20&#xff…...

LVGL简易计算器实战

文章目录 &#x1f4c1; 文件结构建议&#x1f539; eval.h 表达式求值头文件&#x1f539; eval.c 表达式求值实现文件&#xff08;带详细注释&#xff09;&#x1f539; ui.h 界面头文件&#x1f539; ui.c 界面实现文件&#x1f539; main.c 主函数入口✅ 总结 项目效果&…...

【FMMT】基于模糊多模态变压器模型的个性化情感分析

遇到很难的文献看不懂,不应该感到气馁,应该激动,因为外审估计也看不太懂,那么学明白了可以吓唬他 缺陷一:输入依赖性与上下文建模不足​​ ​​缺陷描述​​: 传统自注意力机制缺乏因果关系,难以捕捉序列历史背景多模态数据间的复杂依赖关系未被充分建模CNN/RNN类模型在…...

聊一聊接口测试依赖第三方服务变更时如何处理?

目录 一、依赖隔离与模拟 二、契约测试 三、版本控制与兼容性 四、变更监控与告警 五、容错设计 六、自动化测试维护 七、协作机制与文档自动化 第三方API突然改了参数或者返回结构&#xff0c;导致我们的测试用例失败&#xff0c;这时候该怎么办呢&#xff1f;首先想到…...

代码随想录算法训练营第60期第三十四天打卡

大家好&#xff0c;我们今天的内容依旧是贪心算法&#xff0c;我们上次的题目主要是围绕多维问题&#xff0c;那种时候我们需要分开讨论&#xff0c;不要一起并发进行很容易顾此失彼&#xff0c;那么我们今天的问题主要是重叠区间问题&#xff0c;又是一种全新的贪心算法思想&a…...

Midscene.js Chrome 插件实战:基于 AI 驱动 WEB UI 自动化测试「喂饭教程」

Midscene.js Chrome 插件实战:基于 AI 驱动 WEB UI 自动化测试「喂饭教程」 前言一、Midscene.js 简介二、环境准备与插件安装1. 安装 Chrome 插件2. 配置模型与 API Key三、插件界面与功能总览四、实战演练:用自然语言驱动网页自动化1. 典型场景一(Action):账号登录步骤一…...

JVM——方法内联之去虚化

引入 在Java虚拟机的即时编译体系中&#xff0c;方法内联是提升性能的核心手段&#xff0c;但面对虚方法调用&#xff08;invokevirtual/invokeinterface&#xff09;时&#xff0c;即时编译器无法直接内联&#xff0c;必须先进行去虚化&#xff08;Devirtualization&#xff…...