【JS】对象方法总结
前言
温故知新,顺便做下知识总结。把别人的好文拿来看一遍,顺便做下笔记,瞧一瞧加深记忆。
在 js 中,对象类型是非常重要的类型之一,也是项目中数据处理常用的类型之一,虽然这种类型我们经常使用,但是它的方法却不怎么用的到或者很少用到,不知不觉 js 的对象方法已经来到了 29 个了,今天就来看看这 29 个方法的使用。
还有当 typeof Array 的时候,会发现数组是一个对象类型,也可以说数组是一个特殊的对象,所以大多对象的方法都可以对数组使用,而且有些效果可能会使你大跌眼镜。
正文
Object.defineProperty 劫持对象属性
了解 vue 的应该都比较熟悉这个方法了,因为在 vue2 中,底层的响应拦截就是使用的 Object.defineProperty 加观察者模式实现的。首先说这个是因为描述对象在后面一些方法中都会使用到。
Object.defineProperty 方法接收三个参数,第一个为目标对象,第二个是要添加或修改的属性,三个为描述对象,返回传入的对象。
描述对象的属性:
● configurable 是否可配置的:默认为 false,当为 false 的时候,该属性无法被配置。
● enumerable 是否可枚举:默认 false,当为 false 的时候,该属性无法被枚举,也是就是使用 in 操作符,或者 for in 的时候无法被找到。
● writable 是否可写:默认 false,当为 false 的时候,该属性无法被修改。
● value 属性值:默认 undefined,可以是 js 中的任何类型任何值
● get 方法:返回值默认 undefined。当访问该属性的时候会调用此方法,访问时,所得到的属性值是该方法的返回值。
● set 方法:默认值为 undefined。当修改该属性时会调用此方法。
注意:当配置对象中存在 value 和 writable 属性时,不应该存在 get 和 set 方法,反之亦然。当 value 属性和 get 方法同时存在时,会报错。
1 | const obj = { name: 'iceCode' } |
Object.defineProperties 劫持对象
这个方法可以说是 Object.defineProperty 的强化版,相比较于 Object.defineProperty 每次只能劫持一个属性对其配置,这个方法可以一次性对多个属性进行劫持。
Object.defineProperties 接收两个参数,第一个目标对象,第二个是一个对象,对象的每一个 key 就是要劫持属性值,对象的 value 是该属性值的配置对象。返回目标对象。
Object.assign 对对象的浅拷贝
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
Object.assign 接收两个参数或以上的参数,第一个参数是目标对象,第二个或多是被拷贝的对象,返回目标对象本身。 这里的浅拷贝是将被拷贝对象的属性赋值到目标对象上
1 | const obj = { name: 'iceCode' } |
Object.create 以现有的对象作为原型创建一个新的对象
1 | const obj = { name: 'iceCode' } |
Object.freeze 冻结对象
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze
Object.freeze 方法冻结对象,使目标对象不可配置(使用 Object.defineProperty 等方法修改对象的操作权限),不可扩展,不可删除,不可修改(包括改变原型)。接收一个要被冻结的对象,返回这个对象。
注意:一旦这个对象被冻结,那么这个操作就不可逆,该对象无法被解冻
1 | const obj = { name: 'iceCode' } |
Object.isFrozen 判断对象是否被冻结
- 一个空的不可扩展对象会认为是冻结对象
- 如果一个不可扩展的对象里有属性,且被删除了属性,会认为是冻结对象
- 如果一个不可扩展的对象里有属性,且被配置为不可配置并且不可写( configurable: false,writable: false,),会认为是冻结对象
- 如果一个不可扩展的对象里有一个访问器属性,且被配置为不可配置并且不可写( configurable: false,writable: false,),会认为是冻结对象
- 使用 Object.freeze 冻结一个对象会被认为是冻结对象
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/isFrozen
Object.seal 密封一个对象
Object.seal 密封一个对象,与 Object.freeze 相比可以更改对象中现有的属性,一样不可删除,不可添加等操作
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/seal
1 | const object1 = { |
Object.isSealed 判断一个对象是否被密封
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/isSealed
Object.preventExtensions 禁止对象扩展
可以防止新属性被添加到对象中(即防止该对象被扩展)。它还可以防止对象的原型被重新指定。
Object.isExtensible 判断一个对象是否可扩展
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/isExtensible
Object.fromEntries 将键值对列表转成对象
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/fromEntries
Object.fromEntries 会将键值对格式的列表转化成对象,比如 Map 类型数据,或二维数组数据
1 | const arr: any[] = [ |
Object.prototype.hasOwnProperty 查找对象本身是否存在这个属性
Object.prototype.hasOwnProperty 是一个原型方法,实例对象调用此方法会查找到自身是否存在这个属性,返回一个布尔值,如果自身存在返回 true,如果不存在或或者原型上存在返回 false
1 | const obj = { name: 'iceCode' } |
Object.hasOwn 检查对象本身是否存在这个属性
用法同上,替代版,但有兼容性要求
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwn
如果指定的对象自身有指定的属性,则静态方法 Object.hasOwn() 返回 true。如果属性是继承的或者不存在,该方法返回 false。
Object.getOwnPropertyNames 返回一个包含自身属性(包括不可枚举)的数组
注:本身不包含对象的 Symbol 属性,只包含字符串属性。
Object.getOwnPropertyNames 接收一个目标对象,返回一个数组,包含自身不可枚举的属性,但是不包括 Symbol 属性
Object.getOwnPropertySymbols 返回一个包含自身 Symbol 属性的数组
Object.getOwnPropertySymbols 接收一个目标对象,返回一个数组,只包括目标对象的 Symbol 属性
Object.getPrototypeOf 获取对象的原型
Object.getPrototypeOf 获取目标对象的原型,接收一个参数,返回该目标对象上的原型对象
1 | const obj = { name: 'iceCode', age: 12 } |
Object.setPrototypeOf 修改对象的原型
Object.setPrototypeOf 修改目标对象的原型,接收两个参数,第一个为目标对象,第二个为要设置的原型对象。
Object.prototype.isPrototypeOf 判断一个对象是否存在于另一个对象原型上
Object.prototype.isPrototypeOf 作为 Object 的原型方法,一般用在构造函数上。正常对象也可以使用,同样该方法也是不被保护的。接收一个目标函数,返回一个布尔值。
Object.getOwnPropertyDescriptor 获取自身属性值的描述对象
1 | const object1 = { |
Object.getOwnPropertyDescriptor() 静态方法返回一个对象,该对象描述给定对象上特定属性(即直接存在于对象上而不在对象的原型链中的属性)的配置。返回的对象是可变的,但对其进行更改不会影响原始属性的配置。
Object.getOwnPropertyDescriptors 获取自身所有属性值的描述对象
同上,不过传的是整个对象
Object.prototype.propertyIsEnumerable 表明指定属性是否可枚举
Object.prototype.propertyIsEnumerable 原型方法,表明指定属性是否可枚举,接收一个指定属性的参数,返回要给布尔值
Object.keys 返回自身可枚举属性的数组
Object.keys 接收一个目标对象,返回一个包含自身可枚举属性的数组。就是如果属性被配置为不可枚举或者是 Symbol 属性都无法找到。
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
1 | const f = Symbol('f') |
Object.values 返回自身可枚举属性值的数组
Object.values 接收一个目标对象,返回一个包含自身可枚举属性值的数组。就是如果属性被配置为不可枚举或者是 Symbol 属性都无法获取到这个属性值。
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/values
1 | const arr = [1, 2, 3, 4, 5] |
Object.entries 返回自身可枚举属性和属性值的数组
Object.entries 接收一个目标对象,返回一个包含自身可枚举属性和属性值的二维数组。就是如果属性被配置为不可枚举或者是 Symbol 属性都无法获取到这个属性值。
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/entries
1 | const f = Symbol('f') |
Object.is 对比两个值是否相同
Object.is 会对比两个值是否相同,对比比较操作符更准确,接收两个参数,第一个对比的参数,第二个对比的参数。返回一个布尔值,为对比结果。
Object.prototype.valueOf
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/valueOf
Object.prototype.toString
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/toString
Date.prototype.toLocaleString
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleString
这三个方法都是 Object 原型上的方法,本身在 Object 对象上基本没有任何意义。valueOf 方法旨在被派生对象重写,以实现自定义类型转换逻辑。toSting 方法旨在重写(自定义)派生类对象的类型转换的逻辑。toLocaleString 方法旨在由派生对象重写,以达到其特定于语言环境的目的。
因为 js 中所有类型(不包括 null),都继承 Object 的原型,所有类型都有这三个派生方法,但它们的这三种方法都已经被重写,有着自身不同的效果。这里就不写了,只要知道在 Object 上这三个方法基本没有特殊效果就可以了。
Object.groupBy ES2024 新增
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/groupBy
给定可迭代对象中的元素进行分组
Object.groupBy 方法接收两个参数,第一个是元素分组可迭代的对象(Array 等),第二个是一个回调函数,传递两个参数,第一个参数为当前迭代的元素,第二个为当前迭代的索引。返回的对象具有每个组的单独属性,其中包含组中的元素的数组。
1 | //说起来肯定不太好理解,直接上代码 |
最后
js 中对象的方法虽然有众多,但是业务项目中几乎很少能够用到,如果是比较,感觉还是对比运算符会比 Object.is 更方便一些。如果是对对象进行冻结、密封、禁止扩展的场景更是少之又少,访问原型链在业务需求里也是比较少的。访问对象中是否存在这个属性使用 in 操作符更方便些,但也不乏会有极少数场景可以使用到 Object.hasOwn 等方法
感觉使用 Object.groupBy 对数据进行分组是比较好的方法,但是兼容性可谓是一言难尽。目前使用最多的就是 Object.keys 来对对象进行判断或者遍历