值、对象与集合
JavaScript 对象应按“身份、属性与协议”理解。身份回答两个值是否指向同一实体;属性描述键来自哪里、是否可枚举、读取是否触发代码;协议决定复制、遍历、排序和代理究竟执行哪些操作。不要把对象想成无副作用的 JSON,也不要把数组 length 当成实际元素数量。
核心模型
JavaScript 对象应按“身份、属性与协议”理解。身份回答两个值是否指向同一实体;属性描述键来自哪里、是否可枚举、读取是否触发代码;协议决定复制、遍历、排序和代理究竟执行哪些操作。不要把对象想成无副作用的 JSON,也不要把数组 length 当成实际元素数量。
原理与机制
先定义相等关系,再选择比较工具
=== 不做类型转换,== 按转换规则比较;边界输入宜明确转换。Object.is 把 NaN 视为相同且区分正负零,=== 在这两点上相反。Set、Map 键和 includes 使用 SameValueZero,识别 NaN 且不区分正负零,indexOf 则按严格相等。对象按身份比较,业务实体可按稳定 id;深比较需约定原型、循环、Symbol、Map 等。JSON 字符串不是通用判等:缺失与 undefined 可能合并,键插入顺序又可能让相近内容序列化不同。
属性读取会穿越原型,也可能执行函数
属性先查自身再沿内部原型查找,实例赋同名普通属性通常遮蔽原型,而修改继承数组会影响所有共享者。构造器 prototype 与实例内部原型不同;class 的实例方法通常在原型,字段属于实例,静态成员属于类。Object.keys 取自有可枚举字符串键,for...in 还取继承可枚举字符串键,Reflect.ownKeys 取全部自有键含 Symbol。defineProperty 新属性省略的 writable、enumerable、configurable 默认 false;判断来源用 Object.hasOwn,不能信任对象自带方法。
复制与合并要说明信息损失及写入方式
展开与 Object.assign 复制可枚举自有值,包括 Symbol,都是浅复制且可能读取 getter;assign 还可触发目标 setter,失败时已有写入不回滚。structuredClone 支持多种结构化数据与循环,却不完整保留类原型、描述符、函数或 DOM;transfer 会让源资源失去使用权。JSON.parse 本身不会因 __proto__ 直接污染全局,危险常出现在后续赋值或递归路径合并。外部配置用 schema、允许字段、显式安全默认值;Map 或无原型字典只能保护相应容器。
Proxy 拦截操作,Reflect 保留默认语义
get/set trap 是基本操作入口,Reflect.get(t,k,receiver) 让访问器继续以代理作为 this,因此 getter 内部读取仍可被观测;直接 t[k] 会改变接收者。set 应返回布尔结果,严格模式下失败可能抛 TypeError,还必须遵守不可配置、不可写属性等不变量。代理并不透明:Map 内部槽与 #私有字段可能拒绝代理接收者;改用 target 可修品牌检查,却绕过内部观测。只校验 set 也挡不住 defineProperty、delete 或直接修改暴露 target。
数组方法遵循各自的索引和比较规则
空槽是缺少自有索引,显式 undefined 是索引存在;length 包含空槽。map/forEach 先检查索引及原型链,普通空槽会跳过;迭代器直接读取,展开通常把空槽变成 undefined,includes 也把普通空槽当 undefined,indexOf 通常跳过。delete 留空槽,splice 移位。sort 原地修改,比较器需负数、零、正数并满足一致关系,布尔返回不够;默认按字符串码元排序。toSorted 返回浅新数组,稳定排序保留同键输入顺序,但规范不承诺统一算法和复杂度。
最小示例
javascript预期依次得到 false true、true -1、2 false、6 doubled,n。第一组区分缺失和显式值;第二组说明比较方法并非统一;第三组表明新外壳仍共享内部对象;最后一组说明保留 receiver 后 getter 的内部属性访问再次进入代理。教学日志是有限数组,生产观测不能无界累积。
环境:现代 Node.js;可保存为 .cjs 后执行。
核验:未执行教学示例;说明中的结果为机制推演,不是本轮测试通过记录。
边界与取舍
边界
- Object.assign 已修改的目标不会因后续 getter 抛错回滚;新对象展开失败也不代表 getter 副作用被撤销。
- map 并非绝对跳过所有“空槽位置”,原型链同名索引会参与;练习不要污染全局 Array.prototype。
- toSorted 和对象展开都不是深拷贝;代理字段校验也不等于防篡改或鉴权。
取舍
- 按 id 比较通常更稳定便宜;深比较可验证快照但需明确类型范围和循环策略。
- 不可变更新便于追踪变化,却有复制成本;结构化克隆适合数据快照,类和资源宜显式重建或转移。
口述示范
我先区分对象身份与内容,再说明属性是否自有、可枚举,以及读取是否有副作用。复制、代理和数组方法各走不同协议;测试必须覆盖原型、getter、空槽、NaN 和非法排序值,而不是只验证普通 JSON。
章节练习
参考来源与核验边界
- ECMAScript:Abstract operations · 核验 2026-10-04
- ECMAScript:Ordinary and exotic objects · 核验 2026-10-04
- ECMAScript:Indexed collections · 核验 2026-10-04
- WHATWG:Structured data · 核验 2026-10-04
核验日期 2026-10-04。ECMAScript 在线文档标题显示下一版编辑草案,不把草案标题当成正式发布版本;本章讨论既有机制。toSorted 属 ES2023 方法,旧环境需检查支持。 本章新增示例未在本轮执行,不新增测试通过声明。
内容版本:2026-10-04.2 · 题目和来源 ID 保持原样,本站不将面经标签解释为企业官方出题或高频保证。