Object是 JavaScript 的内置对象,同时也是一个构造函数,可以用它生成新的对象。

JavaScript 的所有其他对象都继承自Object对象,即那些对象都是Object的实例。

Object对象的原生方法分成两类:Object本身的方法()静态方法与Object的实例方法。

Object 对象本身的方法(静态方法)

所谓“本身的方法”就是直接定义在Object对象的方法。

  1. Object.print = function (o) { console.log(o) };

上面代码中,print方法就是直接定义在Object对象上。

Object.defineProperty() 定义/修改属性

Object.defineProperty() 方法可以直接在一个对象上定义一个新的属性,或者修改一个对象的现有属性,返回此对象 它接收了三个参数:

  • 要给其添加属性的对象
  • 属性的名称
  • 描述对象 ```javascript const user = { name: ‘张同学’, age: 38 }

Object.defineProperty(user, ‘friend’, { configurable: true, // 是否可以通过 delete 删除 enumerable: true, // 是否可以循环 writable: true, // 是否可以修改 value: [1, 2, 3, 4] // 添加的值 })

console.log(user) // {name: ‘张同学’, age: 38, friend: Array(4)}

  1. <a name="863cdaa4"></a>
  2. ## Object.defineProperties()
  3. `Object.defineProperties()` 方法和 `Object.defineProperty()` 方法有点类似,`Object.defineProperty()` 只是可以在对象上定义一个属性,而 `Object.defineProperties()` 则可以定义多个
  4. ```javascript
  5. const obj = {}
  6. Object.defineProperties(obj, {
  7. name: {
  8. value: '张同学',
  9. configurable: true
  10. },
  11. age: {
  12. value: 12
  13. }
  14. })
  15. console.log(obj) // {name: '张同学', age: 12}

Object.assign() 合并对象

Object.assign() 可以将对象进行合并,它接收一个目标对象和一个或多个源对象作为参数进行合并

Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象分配到目标对象。它将返回目标对象。它至少需要两个对象作为参数,第一个参数是目标对象,后面的参数都是源对象。
image.png

  1. const obj1 = { a: 1 }
  2. const obj2 = { b: 2 }
  3. Object.assign(obj1, obj2, { c: 12121 })
  4. console.log(obj1) // {a: 1, b: 2, c: 12121}

如果源对象上有很多相同的属性,那么后面的属性会覆盖前面的属性

js

  1. const obj1 = { a: 1 }
  2. Object.assign(obj1, { a: 12, b: 99 }, { b: 21 })
  3. console.log(obj1) // {a: 12, b: 21}

Object.is() 判断相等

Object.is()=== 有点相似

  1. console.log(true === 1) // false
  2. console.log({} === {}) // false

但是有些情况下就会出乎我们的意料

  1. console.log(+0 === -0) // true
  2. console.log(+0 === 0) // true
  3. console.log(-0 === 0) // true

为了改善这种情况,ES6 新增了 Object.is(),可以接收两个参数

  1. console.log(Object.is({}, {})) // false
  2. console.log(Object.is(+0, -0)) // false
  3. console.log(Object.is([], [])) // false
  4. console.log(Object.is('1', 1)) // false
  5. NaN === NaN; // false
  6. Object.is(NaN, NaN); // true

Object.getPrototypeOf() 获取对象原型

用于获取对象的原型,这是标准的方法,__proto__ 本来就是浏览器实现的,所以不是规范的写法,虽然 __proto__Object.getPrototypeOf() 方法都可以正常工作,不过建议使用 Object.getPrototypeOf()

  1. const obj = {}
  2. console.log(obj.__proto__) // {constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
  3. console.log(Object.getPrototypeOf(obj)) // {constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}

不过现在主流的浏览器都已经更新了,对象中不再存在 __proto__ 属性,而是改为了 [[Prototype]]

Object.setPrototypeOf() 重设对象原型

Object.setPrototypeOf() 方法用于重新设置对象的原型

  1. function User() {}
  2. const user = new User()
  3. const newProto = {
  4. satName() {
  5. console.log('你好')
  6. }
  7. }
  8. Object.setPrototypeOf(user, newProto)
  9. console.dir(Object.getPrototypeOf(user))

Object.setPrototypeOf() 可能会影响代码的性能

Object.create()

Object.create() 方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__,接收一个参数是需要继承的原型,如果不想要原型,那么可以传入 null 就是一个纯数据对象

  1. // 纯数据对象
  2. console.log(Object.create(null))
  1. const obj = {
  2. name: '张三',
  3. arr: [1, 2, 3, 4]
  4. }
  5. const newObj = Object.create(obj)
  6. console.log(newObj.__proto__ === obj) // true

因为上述使用 Object.setPrototypeOf() 方法改变对象的原型,可能会导致性能下降,所以可以通过 Object.create() 来创建一个新对象,同时指定原型

它接收一个参数:新创建对象的原型对象

  1. const newProto = {
  2. sayName() {
  3. console.log('你好')
  4. }
  5. }
  6. const user = Object.create(newProto)
  7. user.name = '张同学'
  8. console.dir(user)
  9. console.log(Object.getPrototypeOf(user) === newProto) // true

打印结果

  1. Object
  2. name: "张同学"
  3. [[Prototype]]: Object
  4. satName: ƒ satName()
  5. [[Prototype]]: Object

Object.create 的第二个参数和 Object.defineProperties一样,每个属性都有各自的描述符来描述据。以这种方式添加的属性会遮蔽原型对象上本书的属性

  1. const z = {
  2. name: '张三'
  3. }
  4. const res = Object.create(z, {
  5. name: {
  6. value: '张同学'
  7. }
  8. })
  9. console.log(z.name) // 张同学

:::info 原型式继承非常适合不需要单独创建构造函数,但是仍然需要在对象之间共享信息的场合。但是属性中包含的引用值始终会在香港对象间共享,跟使用原型模式是一样的。 :::

也可以配置对象的内部属性

  1. const obj = { a: '1' }
  2. const o = Object.create(obj, {
  3. b: {
  4. value: '2',
  5. enumerable: true,
  6. writable: false,
  7. configurable: false
  8. },
  9. c: {
  10. value: '3',
  11. enumerable: true,
  12. writable: false,
  13. configurable: false
  14. }
  15. })
  16. console.log(o) // {b: '2', c: '3'}

Object.getOwnPropertyNames()

Object.getOwnPropertyNames() 可以获取对象上所有属性,无论是否可以枚举,都可以获取到,不过仅限于当前作用域对象,不会向上攀升查找

  1. function User() {
  2. this.name = '张三'
  3. this.name2 = '张三'
  4. }
  5. User.prototype.age = 13
  6. const user = new User()
  7. console.log(Object.getOwnPropertyNames(User.prototype)) // ['constructor', 'age']

:::info 在适当的时候,Object.keys() 和 Object.getOwnPropertyNames() 方法可以适当代替 for in 循环操作 :::

Object.getOwnPropertySymbols()

因为 ES6 新增了 Symbol 数据类型,那么针对于 Symbol,普通的循环是遍历不出来的

  1. const key1 = Symbol('key1')
  2. const key2 = Symbol('key2')
  3. const obj = {
  4. [key1]: '张三',
  5. [key2]: 20
  6. }
  7. for (const key in obj) {
  8. console.log(obj[key])
  9. }
  10. // 没有日志输出

所以 Object.getOwnPropertySymbols() 方法是针对于处理 Symbol 数据类型的

  1. const key1 = Symbol('key1')
  2. const key2 = Symbol('key2')
  3. const obj = {
  4. [key1]: '张三',
  5. [key2]: 20
  6. }
  7. for (const key of Object.getOwnPropertySymbols(obj)) {
  8. console.log(obj[key])
  9. }
  10. // 张三
  11. // 20

Object.entries()

该方法会将某个对象的可枚举属性与值按照二维数组的方式返回。(如果目标对象是数组,则会将数组的下标作为键值返回)

image.png

Object.fromEntries

Object.fromEntries() 方法会把键值对列表转换为对象。同 Object.entries() 相反。

  1. const arr = [ [ 'name', 'foo' ], [ 'age', 18 ] ];
  2. const obj = Object.fromEntries(arr);
  3. console.log(obj); // { name: 'foo', age: 18 }
  4. console.log(Object.entries(obj)); // [ [ 'name', 'foo' ], [ 'age', 18 ] ]

Object.keys() 返回对象 key

**Object.keys()** 方法遍历指定对象会返回一个数组,数组元素由该指定对象的key构成。

Object.keys() 方法会返回一个由一个给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和使用 for…in 循环遍历该对象时返回的顺序一致 (两者的主要区别是 一个 for-in 循环还会枚举其原型链prototype上的属性)。

Object - 图3

  1. // simple array
  2. //遍历数组返回下标
  3. var arr = ['a', 'b', 'c'];
  4. console.log(Object.keys(arr)); // console: ['0', '1', '2']
  5. // array like object
  6. var obj = { 0: 'a', 1: 'b', 2: 'c' };
  7. console.log(Object.keys(obj)); // console: ['0', '1', '2']
  8. // array like object with random key ordering
  9. var anObj = { 100: 'a', 2: 'b', 7: 'c' };
  10. console.log(Object.keys(anObj)); // console: ['2', '7', '100']

Object.values() 返回对象 value

它的工作原理和Object.entries()方法很像,但是它只返回键值对中的值,结果是一维数组

  1. Object.values({one: 1, two: 2}) // [1, 2]
  2. Object.values({3: 'a', 1: 'b', 2: 'c'}) // ['b', 'c', 'a']
  3. Object.extries([1, 3]) //[1, 3]

Object.getOwnPropertyDescriptor()

Object.getOwnPropertyDescriptor() 方法可以得到对象属性特征的描述,接收两个参数,第一个是对象名,第二个是对象的属性名

  1. const obj = {
  2. name: '张三',
  3. age: 21
  4. }
  5. console.log(Object.getOwnPropertyDescriptor(obj, 'name'))
  6. // {value: '张三', writable: true, enumerable: true, configurable: true}
  7. // value - 属性值
  8. // writable - 是否可以修改
  9. // enumerable - 是否可以遍历
  10. // configurable - 是否可以被删除或重新配置

Object.getOwnPropertyDescriptors()

上面 Object.getOwnPropertyDescriptor() 方法可以获取对象中单个键的属性特征描述,那么想要获取对象中所有属性的描述,需要使用 Object.getOwnPropertyDescriptors() 方法,该方法接收一个参数为对象名

  1. const obj = {
  2. name: '张三',
  3. age: 21
  4. }
  5. console.log(Object.getOwnPropertyDescriptors(obj))
  6. // {name: {…}, age: {…}, arr: {…}}

Object.preventExtensions()

Object.preventExtensions() 方法可以禁止向对象内添加内容

  1. const obj = {
  2. name: '张三',
  3. age: 21
  4. }
  5. Object.preventExtensions(obj)
  6. obj.a = '1'
  7. console.log(obj) // {name: '张三', age: 21}

Object.seal()

封闭对象,configurable = false不可以被删除或重新配置

可以使用 Object.isSealed() 方法判断当前对象是否处于封闭状态,返回布尔值

  1. const obj = {
  2. name: '张三',
  3. age: 21
  4. }
  5. Object.seal(obj)
  6. // 封闭对象,configurable = false
  7. console.log(Object.isSealed(obj)) // true

Object.freeze()

冻结对象,不能删除或重新配置,也不可以修改

可以使用 Object.isFrozen() 方法判断当前对象是否处于冻结状态,返回布尔值

  1. const obj = {
  2. name: '张三',
  3. age: 21
  4. }
  5. Object.freeze(obj)
  6. // 冻结对象,configurable = false,writable = false
  7. console.log(Object.isFrozen(obj)) // true

hasOwn 检查一个属性是否属于对象

在ES2022之前,可以使用 Object.prototype.hasOwnProperty() 来检查一个属性是否属于对象。

Object.hasOwn 特性是一种更简洁、更可靠的检查属性是否直接设置在对象上的方法:

  1. const example = {
  2. property: '123'
  3. };
  4. console.log(Object.prototype.hasOwnProperty.call(example, 'property'));
  5. console.log(Object.hasOwn(example, 'property'));

Object.hasOwnProperty()

Object.hasOwnProperty() 方法用于检测一个属性是否在来自对象的实例,来自实例返回 true,来着原型返回 false

  1. function User() {
  2. this.name = '张三'
  3. }
  4. User.prototype.age = 13
  5. const user = new User()
  6. console.log(user.hasOwnProperty('name')) // true
  7. console.log(Object.hasOwnProperty.call(user, 'age')) // true

简写方式

  1. function User() {
  2. this.name = '张三'
  3. }
  4. User.prototype.age = 12
  5. const user = new User()
  6. console.log(user.hasOwnProperty('name')) // true
  7. console.log(user.hasOwnProperty('age')) // false

Object.isExtensible()

Object.isExtensible() 方法判断一个对象是否是可扩展的(是否可以在它上面添加新的属性)

  1. const foo = { id: 123 }
  2. console.log(Object.isExtensible(foo)) // true

Object.preventExtensions()

Object.preventExtensions() 方法让一个对象变的不可扩展,也就是永远不能再添加新的属性

  1. const foo = { id: 123 }
  2. console.log(Object.preventExtensions(foo)) // { id: 123 }
  3. foo.age = 12
  4. console.log(foo) // { id: 123 }

isPrototypeOf()

isPrototypeOf() 方法用于测试一个对象是否存在于另一个对象的原型链上

  1. function User() {
  2. this.name = '张三'
  3. }
  4. const user = new User()
  5. console.log(User.prototype.isPrototypeOf(user)) // true

Object 的实例方法

所谓实例方法就是定义在Object原型对象Object.prototype上的方法。它可以被Object实例直接使用。

  1. Object.prototype.print = function () {
  2. console.log(this);
  3. };//创建实例方法
  4. var obj = new Object();//新建实例
  5. obj.print() //obj实例直接使用实例方法

in

in 操作符可以用在两个场景,一个是 for in 循环中,还有一个是单独使用,可以检测对象上是否存在某个属性,无论在实例上还是原型上

  1. function User() {
  2. this.name = '张三'
  3. }
  4. User.prototype.age = 13
  5. const user = new User()
  6. console.log(user.hasOwnProperty('name')) // true
  7. console.log(user.hasOwnProperty('age')) // false
  8. console.log('name' in user) // true
  9. console.log('age' in user) // true