基本特点
- 是一组由 <属性名-属性值> 组成的无序集合
- 包含相关数据和方法的集合(通常由一些变量和函数组成,称之为对象里面的属性和方法)
- 对象的 <属性名> 只能是字符串或者
symbol类型(其他的类型会自动转换为字符串),对象的 <值> 可以是任意类型 - 有特别的顺序:先对自然数属性升序排列,然后字符串属性按照创建时间排序,最后 symbol 属性按创建时间排序
分类
- 用户自定义对象:程序员自己定义
- 内建对象:内置在 JavaScript 语言中定义的对象
- 宿主对象:浏览器等提供的对象
1. 创建
构造函数语法
let obj = new Object()对象字面量语法
let user = {
name: 'xx',
age: 20,
tags: ['HTML5', 'CSS3', 'JavaScript'],
};2. 访问
点运算符
user.name:点运算要求 key 是有效的 变量标识符,注意这里的 name 是一个字符串
方括号运算符
user['name']:如果 key 不是有效的 变量标识符,可以用这种(数字可以不加引号,默认转为字符串)
方括号运算符还可以动态取值:
let obj = {
a: 1
}
let name = 'a'
obj[name] // 1Tip
对象默认有个名为
__proto__的属性,不能将它设置为一个非对象的值。要设置一个这样的属性,可以用 Map
3. 属性
自有属性
对象本身的属性,而不是继承来的属性。
判断方法:Object.hasOwn(obj, prop) 返回 true
可枚举属性
内部 可枚举 标志设置为 true 的属性
判断方法:obj.propertyIsEnumerable(prop) 返回 true
计算属性ES6
可以在对象属性定义中使用方括号动态创建属性,也可以动态访问属性,方括号里可以是任意表达式
let a = 'name'
// 创建
let user = {
[a]: 'xx',
}
// 访问
user[a] // 'xx'属性删除
delete 可以删除不是继承来的属性:delete user.name
属性简写ES6
对象属性名和值一样,直接写一个即可
let name = 'xx'
let age = 20
let user = {
name,
age,
}函数属性
作为对象属性的函数
let user = {
name: 'xx',
getName: function() {
return this.age
}
}方法ES6
省略 “function”
let user = {
name: 'xx',
getName() {
return this.age
}
}方法 和 函数属性 略有区别:
- 方法 中有 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 - 所有环境通用:
globalThisES2020
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 属性 - Symbol 值不能与其他类型的值进行运算
常用方法:
创建
Object.assign ( target, ...sources ):将所有可枚举 的自有 属性(包括 symbol),从一个或多个源对象复制到目标对象,返回修改后的对象,如果被拷贝的属性名已经存在,那么它会被覆盖。
只能拷贝源对象的 可枚举 的 自有 属性,同时无法拷贝属性的描述符,而且访问器属性会被转换成数据属性,也无法拷贝源对象的原型
- 要拷贝属性及原型:
let cloneObj = Object.assign( Object.create( Object.getPrototypeOf(obj) ), obj )
- 要拷贝属性及描述符:
let cloneObj = Object.defineProperties( {}, Object.getOwnPropertyDescriptors(obj) )这种可以完整拷贝:
let cloneObj = Object.create( Object.getPrototypeOf(obj), Object.getOwnPropertyDescriptors(obj) )
-
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