基本特点
- 是一组由 <属性名-属性值> 组成的无序集合
- 包含相关数据和方法的集合(通常由一些变量和函数组成,称之为对象里面的属性和方法)
- 对象的 <属性名> 只能是字符串或者
symbol
类型(其他的类型会自动转换为字符串),对象的 <值> 可以是任意类型 - 有特别的顺序:先对自然数属性升序排列,然后字符串属性按照创建时间排序,最后 symbol 属性按创建时间排序
分类
- 用户自定义对象:程序员自己定义
- 内建对象:内置在 JavaScript 语言中定义的对象
- 宿主对象:浏览器等提供的对象
1. 创建
构造函数语法
对象字面量语法
2. 访问
点运算符
user.name
:点运算要求 key 是有效的 变量标识符,注意这里的 name 是一个字符串
方括号运算符
user['name']
:如果 key 不是有效的 变量标识符,可以用这种(数字可以不加引号,默认转为字符串)
方括号运算符还可以动态取值:
Tip
对象默认有个名为
__proto__
的属性,不能将它设置为一个非对象的值。要设置一个这样的属性,可以用 Map
3. 属性
自有属性
对象本身的属性,而不是继承来的属性。
判断方法:Object.hasOwn(obj, prop)
返回 true
可枚举属性
内部 可枚举 标志设置为 true
的属性
判断方法:obj.propertyIsEnumerable(prop)
返回 true
计算属性ES6
可以在对象属性定义中使用方括号动态创建属性,也可以动态访问属性,方括号里可以是任意表达式
属性删除
delete 可以删除不是继承来的属性:delete user.name
属性简写ES6
对象属性名和值一样,直接写一个即可
函数属性
作为对象属性的函数
方法ES6
省略 “function”
方法 和 函数属性 略有区别:
- 方法 中有 HomeObject 属性,可用于 super 调用
- 方法 不能用作 构造函数
判断属性是否在对象里
in
:判断某个属性在不在对象里,包括 自有属性 和原型继承属性
,也包括 可枚举属性 和不可枚举属性
hasOwnProperty(prop)
:判断 自有属性Object.hasOwn( obj, prop )
:判断 自有属性,但是为静态方法,没有原型的对象也能调用(一般用这个)
属性描述符
对象中的属性描述符分为两类:数据描述符
和 访问器描述符
,每个属性内部都有属性描述符来描述这个属性的特性
value | writable | configurable | enumerable | get | set | |
---|---|---|---|---|---|---|
数据描述符 | √ | √ | √ | √ | ||
访问器描述符 | √ | √ | √ | √ |
一个属性要么是数据属性(有 value/writable 特性),要么是访问器属性(有 get/set 方法)
value
:属性值writable
:true 表示能被赋值运算符改变,false 表示只读configurable
:false 表示属性不可删除,描述符不可修改(除了能将 writable 由 true → false)enumerable
:true 表示可枚举(引入目的是让某些属性规避掉 for…in 操作,不然内部属性和方法都会遍历)get
:访问属性时,会调用此函数(但是不能在外部直接当作函数一样调用它,只能访问它)set
:属性值被修改时,会调用此函数,接受一个参数(也就是被赋予的新值)
使用 Object.defineProperty()
进行设置时,没有提供的描述符默认为 false
遍历
for...in
:遍历所有 可枚举属性 属性,包括继承来的(非 symbol)Object.keys( obj )
:返回 自有属性 可枚举属性 的属性名组成的数组(非 symbol)Object.values( obj )
:返回 自有属性 可枚举属性 的属性值组成的数组(非 symbol)Object.entries( obj )
:返回 自有属性 可枚举属性 组成的键值对数组(非 symbol)Object.getOwnPropertyNames( obj )
:返回 自有属性 的所有(非 Symbol)的属性名数组Object.getOwnPropertySymbols( obj )
:返回 自有属性 的所有 Symbol 属性名的数组Reflect.ownKeys( obj )
:包含 自有属性 的所有键名,不管键名是 Symbol 或字符串,也不管是否可枚举
以上遍历方法都遵循下面规则:
- 首先遍历所有数值键,按照数值升序排列
- 其次遍历所有字符串键,按照加入时间升序排列
- 最后遍历所有 Symbol 键,按照加入时间升序排列
对象复制
浅拷贝
深拷贝
JSON.parse( JSON.stringify(obj) )
:对于不可序列化的属性会失效_.cloneDeep(obj)
:lodash 库函数structuredClone()
全局对象
可在任何地方使用的变量和函数
- 浏览器 中:
window
- Node.js 中:
global
- 所有环境通用:
globalThis
ES2020
SymbolES6
带有可选描述的“原始唯一值”,目前 symbol
类型值的唯一目的就是作为对象不重复的属性名。
- 创建:
let id = Symbol()
- 添加描述(name):
let id = Symbol(id)
- 对象字面量中的 symbol:需要用方括号括起来:
let obj = { [id]: 123 }
- 全局 symbol:用于相同的描述取到相同的 symbol,如:
let x = Symbol.for('id')
,let y = Symbol.for('id')
,则x===y
特性:
- 不参与
for...in
循环 Object.keys()
,Object.values()
,Object.entries()
也会忽略它们Object.assign()
会同时复制字符串和 symbol 属性- 展开语法
{ ...obj }
会同时复制字符串和 symbol 属性
常用方法:
创建
Object.assign( target, ...sources )
:将所有 可枚举 的 自有 属性(包括 symbol),从一个或多个源对象复制到目标对象,返回修改后的对象,如果被拷贝的属性名已经存在,那么它会被覆盖。
只能拷贝源对象的 可枚举 的 自有 属性,同时无法拷贝属性的描述符,而且访问器属性会被转换成数据属性,也无法拷贝源对象的原型
- 要拷贝属性及原型:
- 要拷贝属性及描述符:
这种可以完整拷贝:
-
Object.create( prototype [, propertiesObject] )
:返回根据指定的原型对象和属性描述创建的新对象 -
Object.fromEntries( iterable )
:从生成键值对的可迭代对象中创建新对象
判断
hasOwnProperty( prop )
:判断一个对象的属性是否是 自有 属性Object.hasOwn ( instance, prop )
:同上,但是为静态方法,没有原型的对象也能调用判断ES2020Object.is ( value1, value2 )
:判断两个值是否为同一个值ES6Object.isExtensible( obj )
:判断对象是否可扩展(可以在它上面添加新的属性)Object.isSealed( obj )
:判断是否 自有 属性 都是 不可扩展,不可配置Object.isFrozen( obj )
:判断是否 自有 属性 都是 不可扩展,不可配置,且所有数据属性都是不可写的propertyIsEnumerable( prop )
:判断指定的属性名是否是 可枚举 的 自有 属性isPrototypeOf( obj )
:判断一个对象是否存在于 obj 的原型链上
获取
Object.getOwnPropertyDescriptor( obj, prop )
:返回 obj 对象中 自有 属性 prop 对应的属性描述符Object.getOwnPropertyDescriptors( obj )
:返回所有 自有 属性的描述符Object.getOwnPropertyNames( obj )
:返回 自有 的所有(非 Symbol)的属性名数组Object.getOwnPropertySymbols( obj )
:返回 自有 的所有 Symbol 属性名的数组Object.getPrototypeOf( obj )
:返回指定对象的原型Object.keys( obj )
:返回 可枚举 的 自有 属性名组成的数组Object.values( obj )
:返回 可枚举 的 自有 属性值组成的数组Object.entries( obj )
:返回 可枚举 的 自有 属性组成的键值对数组
设置
Object.defineProperty( obj, prop, descriptor )
:在对象上定义新属性,或修改现有属性Object.defineProperties( obj, props )
:同上,批量Object.preventExtensions( obj )
:禁止 添加 属性Object.seal( obj )
:禁止 添加/删除 属性
为所有自身现有的属性设置 configurable: false
Object.freeze( obj )
:禁止 添加/删除/更改 属性
为所有自身现有的属性设置 configurable: false, writable: false
Object.setPrototypeOf( obj, prototype )
:重新设置 obj 对象的原型
深入理解JavaScript——Object.create - 知乎 (zhihu.com)
javascript - Difference between freeze and seal - Stack Overflow