菜单

对象值

相关源文件

本文档解释了 JavaScript 的对象值在类型系统中是如何工作的。对象是 JavaScript 的基本值类型之一,与原始值不同,理解它们的行为对于有效的 JavaScript 编程至关重要。有关原始值(如字符串、数字和布尔值)的信息,请参阅原始值

对象值的特征

JavaScript 中的对象值具有几个关键特征,使其区别于原始值

  1. 可变 - 与原始值不同,对象可以在创建后进行修改
  2. 基于引用 - 变量存储的是对象的引用,而不是对象本身
  3. 面向集合 - 它们作为属性的集合,存储其他值
  4. 类型专用 - 存在几种具有独特行为的专用子类型

对象值与原始值

来源:types-grammar/ch3.md14-26 types-grammar/ch1.md8-26

可变性与不变性

对象在创建后可以被修改,而原始值是不可变的。这是它们行为方式的一个根本区别

来源:types-grammar/ch2.md14-46 types-grammar/ch3.md8-14

对象类型

JavaScript 的对象值类型包含几种子类型,每种都有其专门的行为

对象类型描述使用示例
普通对象基本的键值集合{name: "Kyle", age: 39}
基础对象包装原始值new String("hello")
数组数字索引集合[1, 2, 3]
函数可调用对象function() {}
正则表达式模式匹配/[a-z]+/g
其他内置对象Date, Error, Map 等。new Date()

来源:types-grammar/ch3.md14-26 types-grammar/toc.md26-35

普通对象

普通对象(有时称为“POJOs”——Plain Old JavaScript Objects)是最常见的对象类型。它们充当命名属性的集合,每个属性保存任何类型的值。

创建和使用

默认情况下,普通对象与[[Prototype]] 链接到Object.prototype,使它们能够访问内置方法,如toString()valueOf()等。

来源:types-grammar/ch3.md28-67

对象引用

与按值复制的原始值不同,对象是按引用赋值的

当你将一个对象赋值给一个变量或将其传递给一个函数时,你操作的是该对象的引用,而不是一个新副本。这导致了 JavaScript 中一个非常常见的陷阱:多个变量可以指向同一个对象,通过任何一个引用进行的修改都会影响底层对象。

来源:types-grammar/ch2.md103-130

基础对象(包装原始值)

JavaScript 为原始类型提供了对象包装构造函数

  • new String() - 包装字符串原始值
  • new Number() - 包装数字原始值
  • new Boolean() - 包装布尔值原始值

由于 JavaScript 会自动执行自动装箱,这些很少需要直接使用。

自动装箱机制

当在原始值上访问属性或方法时,JavaScript 会自动将该原始值包装到其对应的对象类型中

这发生在后台,并允许原始值表现得好像它们具有属性和方法一样

来源:types-grammar/ch3.md68-146 types-grammar/ch1.md65-91

数组

数组是经过优化的、用于数字索引值集合的专用对象

数组与Array.prototype 具有[[Prototype]] 链接,这使它们能够访问各种数组特有的方法

  • 可变方法:push()pop()sort() 等。
  • 不可变方法:map()filter()concat() 等。
  • 访问器方法:indexOf()includes() 等。

尽管有特殊处理,数组本质上仍然是对象,甚至可以向其添加命名属性(尽管不推荐这样做)。

来源:types-grammar/ch3.md158-189

函数

JavaScript 中的函数是专门的对象,可以被调用或执行。与许多其他语言不同,JavaScript 函数是第一类值,可以被

  • 赋值给变量
  • 作为参数传递
  • 从其他函数返回
  • 拥有属性和方法

作为对象,函数具有特殊属性,如namelength(声明的参数数量),以及call()apply() 等方法。

来源:types-grammar/ch3.md194-196 types-grammar/toc.md33

对象强制类型转换行为

与具有相当直接的强制类型转换规则的原始值不同,对象具有特殊的强制类型转换行为

  1. 当强制转换为字符串时:调用对象的toString() 方法,如果需要则回退到valueOf()
  2. 当强制转换为数字时:调用对象的valueOf() 方法,如果需要则回退到toString()
  3. 当强制转换为布尔值时:始终强制为true(所有对象都是“真值”)

此行为在ToPrimitive() 抽象操作中得到正式定义,该操作在强制类型转换期间被调用。

来源:types-grammar/ch4.md87-105 types-grammar/ch4.md151-166

未来方向:记录和元组

JavaScript 有一个提案(撰写时处于第二阶段),关于记录(Records)和元组(Tuples)——对象和数组的不可变版本,它们的行为更像原始值

  • 记录 (#{name: "Kyle"}) - 对象的不可变替代品
  • 元组 (#[1, 2, 3]) - 数组的不可变替代品

这些将是原始值(不是对象),使它们不可变,并允许它们通过值而不是引用进行比较。

来源:types-grammar/ch3.md198-206

常用对象操作

操作描述示例
属性访问获取命名属性的值obj.propobj["prop"]
属性赋值设置命名属性的值obj.prop = value
属性存在性检查测试属性是否存在"prop" in objobj.hasOwnProperty("prop")
属性枚举列出属性Object.keys(obj)for..in 循环
属性删除删除属性delete obj.prop
对象比较按引用比较obj1 === obj2(仅当引用相同时为 true)
对象复制创建浅拷贝Object.assign({}, obj){...obj}

来源:types-grammar/ch3.md28-67

JavaScript 中对象值的这些基本方面为在语言中组织代码、表示数据和构建抽象提供了基础。