JavaScript 的“世界模型”:深入理解对象 (Objects)
引言:超越简单值,构建复杂实体
到目前为止,我们学习的变量大多存储的是单一的值,比如一个数字 (let age = 30;)、一个字符串 (let name = "Alice";) 或一个布尔值 (let isActive = true;)。这对于简单场景足够了,但现实世界是复杂的。如何表示一个包含多个相关信息的东西,比如一个“用户”?一个用户有名字、年龄、邮箱、地址等等属性。
这就是对象 (Object) 大显身手的地方。在 JavaScript 中,对象是一种复合数据类型,它允许我们将多个键值对 (key-value pairs) 组合在一起,用来描述一个实体(比如一个人、一辆车、一个订单)的特征和行为。
你可以把对象想象成一个现实世界物体的数字模型,或者一个包含各种相关信息的“档案袋”。它是 JavaScript 中组织和管理数据的基本方式,理解它对于后续学习框架、API 交互等至关重要。
准备好探索如何用代码构建你自己的“世界模型”了吗?
一、创建对象:组装你的“档案袋”
创建对象最常用、最直观的方式是使用对象字面量 (Object Literal) 语法,也就是用一对大括号 {}。
// 创建一个空对象
let emptyObject = {};// 创建一个表示用户的对象
let user = {// 键 (key) : 值 (value)name: "Bob", // 属性 name,值是字符串 "Bob"age: 28, // 属性 age,值是数字 28isAdmin: false, // 属性 isAdmin,值是布尔值 false"e-mail": "bob@example.com", // 键包含特殊字符,必须用引号包裹address: { // 值可以是另一个对象(嵌套对象)street: "123 Main St",city: "Anytown"},hobbies: ["reading", "music", "hiking"] // 值可以是数组
};
-
键 (Key)/属性名 (Property Name):
- 通常是字符串。如果键名符合变量命名规则(不含空格、特殊字符,不以数字开头),则引号可以省略(如 name, age)。否则,必须用引号包裹(如 "e-mail")。
- 也可以是 ES6 引入的 Symbol 类型。
-
值 (Value)/属性值 (Property Value):
- 可以是任何 JavaScript 数据类型:String, Number, Boolean, null, undefined, Symbol, BigInt, 甚至可以是另一个对象或数组或函数。
-
键值对: 每个 key: value 组合称为对象的一个属性 (Property)。属性之间用逗号 , 分隔。
另一种方式:new Object() (不常用)
你也可以使用 new Object() 构造函数来创建对象,然后逐个添加属性。但这种方式比较冗长,通常我们优先使用对象字面量。
let car = new Object();
car.make = "Toyota";
car.model = "Camry";
car.year = 2022;
二、访问属性:从“档案袋”里取东西
创建了对象,如何获取里面存储的信息呢?主要有两种方式:
1. 点符号 (Dot Notation): object.propertyName
这是最常用、最简洁的方式。直接在对象名后面跟一个点 .,然后是属性名。
console.log(user.name); // 输出: Bob
console.log(user.age); // 输出: 28
console.log(user.address.city); // 访问嵌套对象的属性: Anytown
console.log(user.hobbies[0]); // 访问数组属性的元素: reading// console.log(user."e-mail"); // 错误!点符号不能用于带特殊字符的键
- 限制: 属性名必须是有效的 JavaScript 标识符(不能是纯数字,不能包含空格或特殊字符等)。
2. 方括号符号 (Bracket Notation): object['propertyName']
这种方式更灵活,方括号 [] 里面放的是一个字符串(或者能计算出字符串的表达式,比如变量),这个字符串就是你要访问的属性名。
console.log(user['name']); // 输出: Bob
console.log(user['age']); // 输出: 28
console.log(user['address']['city']); // 访问嵌套对象
console.log(user['hobbies'][1]); // 访问数组元素: music
console.log(user['e-mail']); // 正确!可以访问带特殊字符的键// 使用变量作为键名
let propertyToAccess = "isAdmin";
console.log(user[propertyToAccess]); // 输出: false (访问 user['isAdmin'])let keyPart1 = "addr";
let keyPart2 = "ess";
console.log(user[keyPart1 + keyPart2].street); // 输出: 123 Main St (访问 user['address'].street)
-
优势:
- 可以访问任何字符串作为键名,包括包含空格、特殊字符、或者以数字开头的键。
- 可以用变量来动态指定要访问的属性名。
访问不存在的属性:
如果尝试访问一个对象上不存在的属性,不会报错,而是会返回 undefined。
console.log(user.gender); // 输出: undefined
console.log(user['phone number']); // 输出: undefined
三、修改属性:更新“档案袋”里的信息
对象的属性不是一成不变的,你可以随时修改它们。
1. 更新现有属性:
直接使用点符号或方括号符号,像给变量赋值一样,给属性赋一个新值。
user.age = 29; // 更新 age 属性
user['isAdmin'] = true; // 更新 isAdmin 属性
user.address.city = "New City"; // 更新嵌套对象的属性console.log(user.age); // 输出: 29
console.log(user.isAdmin); // 输出: true
console.log(user.address.city); // 输出: New City
2. 添加新属性:
如果赋值给一个对象上不存在的属性,JavaScript 会自动为你创建这个新属性。
user.country = "USA"; // 添加新的 country 属性
user['phone number'] = "123-456-7890"; // 添加新的带空格的属性console.log(user.country); // 输出: USA
console.log(user['phone number']); // 输出: 123-456-7890
3. 删除属性:
使用 delete 运算符可以从对象中删除一个属性。
delete user.hobbies; // 删除 hobbies 属性
console.log(user.hobbies); // 输出: undefineddelete user['e-mail']; // 删除 'e-mail' 属性
console.log(user['e-mail']); // 输出: undefined
delete 操作成功会返回 true(即使属性原本就不存在也返回 true)。
四、当属性是函数时:方法 (Methods)
对象的属性值不仅可以是数据,还可以是函数!当一个对象的属性值是函数时,我们通常称这个属性为该对象的方法 (Method)。方法定义了对象的“行为”。
let calculator = {operand1: 0,operand2: 0,// 定义一个 add 方法add: function() {// 在方法内部,`this` 通常指向调用该方法的对象本身return this.operand1 + this.operand2;},// 使用 ES6 简洁语法定义 subtract 方法subtract() {return this.operand1 - this.operand2;},// 箭头函数作为方法(注意 this 的区别,后面详述)// multiply: () => { /* ... this behaves differently here ... */ }
};// 设置操作数
calculator.operand1 = 10;
calculator.operand2 = 5;// 调用方法,就像访问属性一样,但后面要加圆括号 ()
let sumResult = calculator.add();
console.log("Sum:", sumResult); // 输出: Sum: 15let diffResult = calculator.subtract();
console.log("Difference:", diffResult); // 输出: Difference: 5
- 调用方法: 使用点符号或方括号访问到函数属性后,加上圆括号 () 来执行它。
- this 关键字初探: 在普通函数(非箭头函数)作为方法被调用时,函数内部的 this 关键字通常会指向调用该方法的那个对象(在上面的例子中,this 指向 calculator 对象)。这使得方法可以访问和操作对象自身的其他属性。关于 this 的复杂性,我们后续会有专门的篇章深入探讨。
五、遍历对象属性:查看“档案袋”里的所有条目
有时候,你需要知道一个对象里到底有哪些属性,或者需要依次处理每个属性。
1. for...in 循环:
这是专门用来遍历对象可枚举属性 (enumerable properties) 的键 (key) 的循环。
let carInfo = {make: "Honda",model: "Civic",year: 2020,color: "blue"
};for (let key in carInfo) {// key 变量在每次迭代中会是对象的一个属性名 (字符串)console.log(`Property: ${key}, Value: ${carInfo[key]}`);// 注意:这里必须用方括号 carInfo[key] 来访问属性值,// 因为 key 是一个包含属性名的字符串变量,不能用点符号 carInfo.key
}
/* 输出:
Property: make, Value: Honda
Property: model, Value: Civic
Property: year, Value: 2020
Property: color, Value: blue
*/
- 注意: for...in 不仅会遍历对象自身的属性,还可能遍历到其原型链上继承来的可枚举属性(后续讲原型时会细说)。如果你只想遍历对象自身的属性,通常需要配合 hasOwnProperty() 方法检查。
2. Object.keys(), Object.values(), Object.entries() (ES6+)
这些是更现代、更推荐的方法,它们只关注对象自身的可枚举属性,并返回数组,可以方便地配合数组方法(如 forEach)或 for...of 循环使用。
- Object.keys(obj): 返回一个包含对象所有自身可枚举属性键名的数组。
- Object.values(obj): 返回一个包含对象所有自身可枚举属性值的数组。
- Object.entries(obj): 返回一个包含对象所有自身可枚举属性 [key, value] 对的数组。
let fruitBasket = {apple: 5,banana: 3,orange: 8
};let keys = Object.keys(fruitBasket);
console.log(keys); // 输出: ["apple", "banana", "orange"]let values = Object.values(fruitBasket);
console.log(values); // 输出: [5, 3, 8]let entries = Object.entries(fruitBasket);
console.log(entries); // 输出: [ ["apple", 5], ["banana", 3], ["orange", 8] ]// 使用 for...of 遍历 entries
console.log("--- Using Object.entries with for...of ---");
for (let [key, value] of Object.entries(fruitBasket)) {console.log(`${key}: ${value}`);
}
/* 输出:
apple: 5
banana: 3
orange: 8
*/
通常推荐使用 Object.keys/values/entries 结合数组方法或 for...of 来遍历对象属性,因为它们更可控、更清晰。
六、对象是“引用类型”
回顾一下,我们之前接触的基本数据类型(String, Number, Boolean, Null, Undefined, Symbol, BigInt)都是原始类型 (Primitive Types)。当你把一个原始类型的值赋给另一个变量时,是复制了这个值。
let x = 10;
let y = x; // y 得到的是 x 的值的副本 (10)
y = 20; // 修改 y 不会影响 x
console.log(x); // 输出: 10
而对象 (以及数组和函数) 属于引用类型 (Reference Types)。当你把一个对象赋给另一个变量时,你复制的不是对象本身,而是指向该对象的内存地址(引用)。这意味着这两个变量实际上指向同一个对象。
let obj1 = { value: 10 };
let obj2 = obj1; // obj2 得到的是 obj1 的引用 (指向同一个对象)obj2.value = 20; // 通过 obj2 修改对象
console.log(obj1.value); // 输出: 20 (obj1 也被影响了,因为它们指向同一个对象!)obj1.newValue = 30; // 通过 obj1 添加属性
console.log(obj2.newValue); // 输出: 30 (obj2 也能看到这个新属性)
理解引用类型非常重要,尤其是在函数参数传递、对象比较等方面,它会影响代码的行为。
相关文章:
JavaScript 的“世界模型”:深入理解对象 (Objects)
引言:超越简单值,构建复杂实体 到目前为止,我们学习的变量大多存储的是单一的值,比如一个数字 (let age 30;)、一个字符串 (let name "Alice";) 或一个布尔值 (let isActive true;)。这对于简单场景足够了&am…...

Java集成【邮箱验证找回密码】功能
目录 1.添加依赖 2.选择一个自己的邮箱,作为发件人角色。 3.编写邮箱配置【配置发件人邮箱】 4.编写邮箱配置类 5.编写controller业务代码 6.演示效果 7.总结流程 8.注意 结语 一.发送邮箱验证码 1.添加依赖 <!--导入邮箱依赖--> <dependency&g…...

HarmonyOS 5.0应用开发——MVVM模式的应用
【高心星出品】 文章目录 MVVM模式的应用ArkUI开发模式图架构设计原则案例运行效果项目结构功能特性开发环境model层viewmodel层view层 MVVM模式的应用 MVVM(Model-View-ViewModel)模式是一种广泛用于应用开发的架构模式,它有助于分离应用程…...

程序员鱼皮最新项目-----AI超级智能体教程(一)
文章目录 1.前言1.什么是AI大模型2.什么是多模态3.阿里云百炼平台介绍3.1文本调试展示3.2阿里云和dashscope的关系3.3平台智能体应用3.4工作流的创建3.5智能体编排应用 1.前言 最近鱼皮大佬出了一套关于这个AI 的教程,关注鱼皮大佬很久了,鱼皮大佬确实在…...

【AI模型学习】双流网络——更强大的网络设计
文章目录 一 背景1.1 背景1.2 研究目标 二 模型2.1 双流架构2.2 光流 三 实验四 思考4.1 多流架构4.2 fusion策略4.3 fusion的early与late 先简单聊了双流网络最初在视频中的起源,之后把重点放在 “多流结构"和"fusion” 上。 一 背景 1.1 背景 Two-Str…...

HarmonyOS:一多能力介绍:一次开发,多端部署
概述 如果一个应用需要在多个设备上提供同样的内容,则需要适配不同的屏幕尺寸和硬件,开发成本较高。HarmonyOS 系统面向多终端提供了“一次开发,多端部署”(后文中简称为“一多”)的能力,可以基于一种设计…...

“在中国,为中国” 英飞凌汽车业务正式发布中国本土化战略
3月28日,以“夯实电动化,推进智能化,实现高质量发展”为主题的2025中国电动汽车百人会论坛在北京举办。众多中外机构与行业上下游嘉宾就全球及中国汽车电动化的发展现状、面临的挑战与机遇,以及在技术创新、市场布局、供应链协同等…...
《Pinia 从入门到精通》Vue 3 官方状态管理 -- 基础入门篇
《Pinia 从入门到精通》Vue 3 官方状态管理 – 基础入门篇 《Pinia 从入门到精通》Vue 3 官方状态管理 – 进阶使用篇 《Pinia 从入门到精通》Vue 3 官方状态管理 – 插件扩展篇 📖 教程目录 为什么选择 Pinia?1.1 背景介绍1.2 Vuex 的痛点(对…...

Java技术体系的主要产品线详解
Java技术体系的主要产品线详解 Java Card:支持Java小程序(Applets)运行在小内存设备(如智能卡)上的平台。 Java ME(Micro Edition):支持Java程序运行在移动终端(手机、P…...

机器学习快速入门--0算力起步实践篇
在学习人工智能的过程中,显卡是必不可少的工具,但它的成本较高且更新换代速度很快。那么,没有GPU的情况下如何学习人工智能呢?以下是针对普通电脑与有算力环境分离的学习规划方案,尤其适合前期无GPU/云计算资源的学习者…...
MySQL 详解之索引:提升查询效率的秘密武器
在数据库的世界里,数据量通常是巨大的。想象一下,一个拥有数百万甚至数十亿条记录的表格,如果你需要从中查找符合特定条件的几条甚至一条记录,数据库是如何快速找到它们的呢?如果没有高效的机制,数据库不得不一条条地遍历整个表格,这无疑会非常缓慢和耗费资源。这时,索…...
中通 Redis 集群从 VM 迁移至 PVE:技术差异、PVE 优劣势及应用场景深度解析
在数字化转型浪潮下,企业对服务器资源的高效利用与成本控制愈发重视。近期,中通快递将服务器上的 Redis 集群服务从 VM(VMware 虚拟化技术)迁移至 PVE(Proxmox VE),这一技术举措引发了行业广泛关…...

源码篇 剖析 Vue2 双向绑定原理
前置操作 源码代码仓地址:https://github.com/vuejs/vue/tree/main 1.查看源码当前版本 当前版本为 v2.7.16 2.Clone 代码 在【Code】位置点击,复制 URL 用于 Clone 代码 3.执行 npm install 4.执行 npm run dev 前言 在 Vue 中最经典的问题就是双…...
Restful接口学习
一、为什么RESTful接口是数据开发的核心枢纽? 在数据驱动的时代,RESTful接口如同数据高速公路上的收费站,承担着数据交换的核心职责。数据工程师每天需要面对: 异构系统间的数据交互(Hadoop集群 ↔ 业务系统…...
C++ round 函数笔记 (适用于算法竞赛)
在算法竞赛中,处理浮点数并将其转换为整数是常见的需求,round 函数是标准库提供的用于执行“四舍五入”到最近整数的工具。理解其工作方式和潜在问题对于避免错误至关重要。 1. 基本用法 头文件 要使用 round 函数,需要包含 <cmath>…...
1.5软考系统架构设计师:架构师的角色与能力要求 - 超简记忆要点、知识体系全解、考点深度解析、真题训练附答案及解析
超简记忆要点 角色职责 需求规划→架构设计→质量保障 能力要求 技术(架构模式/性能优化) 业务(模型抽象→技术方案) 管理(团队协作/风险控制) 知识体系 基础:CAP/设计模式/网络协议案例&am…...

单例模式与消费者生产者模型,以及线程池的基本认识与模拟实现
前言 今天我们就来讲讲什么是单例模式与线程池的相关知识,这两个内容也是我们多线程中比较重要的内容。其次单例模式也是我们常见设计模式。 单例模式 那么什么是单例模式呢?上面说到的设计模式又是什么? 其实单例模式就是设计模式的一种。…...
JAVA程序获取SVN提交记录
1.获取文件提交记录 private String userName "userName "; //svn账号 private String password "password "; //svn密码 private String urlString "urlString "; //svnurl 换成自己对应的svn信息 package com.tengzhi.common.dao;import…...

STM32配置系统时钟
1、STM32配置系统时钟的步骤 1、系统时钟配置步骤 先配置系统时钟,后面的总线才能使用时钟频率 2、外设时钟使能和失能 STM32为了低功耗,一开始是关闭了所有的外设的时钟,所以外设想要工作,首先就要打开时钟,所以后面…...

React 与 Vue:两大前端框架的深度对比
在前端开发领域,React 和 Vue 无疑是当下最受欢迎的两大框架。它们各自拥有独特的优势和特点,吸引了大量开发者。无论是初学者还是经验丰富的工程师,选择 React 还是 Vue 都是一个常见的问题。本文将从多个角度对 React 和 Vue 进行对比&…...
Node.js 学习入门指南
Node.js 学习入门指南 Node.js 是一种流行的开源、跨平台的 JavaScript 运行时环境,它使开发者能够在服务器端运行JavaScript代码。本篇文章旨在帮助初学者快速入门并掌握Node.js的基础知识和常用技巧。 一、什么是Node.js? 定义 Node.js 是一个基于…...

Java24新增特性
Java 24(Oracle JDK 24)作为Java生态的重要更新,聚焦AI开发支持、后量子安全、性能优化及开发者效率提升,带来20余项新特性和数千项改进。以下是核心特性的分类解析: 一、语言特性增强:简化代码与模式匹配 …...

Sentinel源码—6.熔断降级和数据统计的实现一
大纲 1.DegradeSlot实现熔断降级的原理与源码 2.Sentinel数据指标统计的滑动窗口算法 1.DegradeSlot实现熔断降级的原理与源码 (1)熔断降级规则DegradeRule的配置Demo (2)注册熔断降级监听器和加载熔断降级规则 (3)DegradeSlot根据熔断降级规则对请求进行验证 (1)熔断降级…...

Volcano 实战快速入门 (一)
一、技术背景 随着大型语言模型(LLM)的蓬勃发展,其在 Kubernetes (K8s) 环境下的训练和推理对资源调度与管理提出了前所未有的挑战。这些挑战主要源于 LLM 对计算资源(尤其是 GPU)的巨大需求、分布式任务固有的复杂依…...
快速体验tftp文件传输(嵌入式设备)
一、参考资料 Linux tftp 命令 | 菜鸟教程 Ubuntu最新版本(Ubuntu22.04LTS)安装Tftp服务及其使用教程-CSDN博客 Windows下的Tftpd32(Tftpd64)软件下载和使用教程-集成了Tftp服务器、客户端-CSDN博客 tftpd32 tftpd64文件传输安装和使用教程【图文并茂】-CSDN博客 二、快速…...

用交换机连接两台电脑,电脑A读取/写电脑B的数据
1、第一步,打开控制面板中的网络和共享中心,如下图配置,电脑A和电脑B均要配置; 注意:要保证电脑A和电脑B在同一子网掩码下,不同的IP地址; 2、在电脑上同时按‘CommandR’,在弹出的输…...

问道数码兽 怀旧剧情回合手游源码搭建教程(反查重优化版)
本文将对"问道数码兽"这一经典卡通风格回合制手游的服务端部署与客户端调整流程进行详细拆解,适用于具备基础 Windows 运维和手游源码调试经验的开发者参考使用。教程以实战为导向,基于原始说明内容重构优化,具备较高的内容查重避重…...

WLAN共享给以太网后以太网IP为169.254.xx.xx以及uboot无法使用nfs下载命令的的解决方案
WLAN共享网络给以太网,实际上是把以太网口当作一个路由器,这个路由器的IP是由WLAN给他分配的,169.254.xx.xx是windows设定的ip,当网络接口无法从上一级网络接口获得ip时,该网络接口的ip被设置为169.254 ,所…...
Gazebo 仿真环境系列教程(一):环境安装与基础使用
文章目录 一、版本说明与技术背景1.1 Gazebo 版本分支1.2 版本选择建议 二、系统环境准备2.1 硬件要求2.2 软件依赖 三、Gazebo Garden 安装流程3.1 添加官方软件源3.2 执行安装命令3.3 环境验证 四、Gazebo Classic 安装方法4.1 添加软件仓库4.2 安装核心组件4.3 验证安装 五、…...

ROS 快速入门教程03
8.编写Subscriber订阅者节点 8.1 创建订阅者节点 cd catkin_ws/src/ catkin_create_pkg atr_pkg rospy roscpp std_msgs ros::Subscriber sub nh.subscribe(话题名, 缓存队列长度, 回调函数) 回调函数通常在你创建订阅者时定义。一个订阅者会监听一个话题,并在有…...