Skip to content

Object对象

Object 是一个 JS 原生提供的对象,它是一个工具函数,一个实例对象,一个构造函数。

一个工具函数: Object 本身是一个函数,可以将任意值转为对象

一个实例对象: Object 这个对象的原型上挂载了一系列方法,这些方法,我们称之为实例方法,我们可以通过 Object 这个对象访问到, 比如,Object.keys()

一个构造函数 我们可以用 new Object() 来生成新对象

一个工具函数 Object()

我们用Object(x) 来把 x 转为对象或者说保证它是对象

js
// 构建空对象
const obj1 = Object()
const obj2 = Object(undefined)
const obj3 = Object(null)
const obj4 = {}
console.log(obj1, obj2, obj3, obj4) // {} {} {} {}
js
// 把基本类型包装
const obj1 = Object(1)      // Number{1}
const obj2 = Object('foo')  // String{'foo'}
const obj3 = Object(false)  // Boolean{false}

console.log(typeof obj1) // object
console.log(1 instanceof Number, obj1 instanceof Number)// false, true

一个构造函数 new Object()

Object 的构造函数用法new Object()和工具函数 Object() 的用法几乎一摸一样,如果传入的是一个对象,那么直接返回这个对象,如果是原始类型,则返回包装对象

再强调一下:如果参数本身就是对象,虽然是new,但是不会开辟新的堆空间并深拷贝一个同样的对象,而是直接返回原本的对象

js
const o = { name: 'jack' }
const obj1 = Object(o)
const obj2 = new Object(o)

console.log(o === obj1, obj1 === obj2) // true

一个实例对象 Object.xxx

Object作为一个实例对象,它本身上有很多方法,它的原型上也挂载了很多方法。

Object的自身方法

获取对象的key

Object.keys() 返回对象自身的可枚举的属性

Object.getOwnPropertyNames() 返回对象自身的,全部属性、

Object.getOwnPropertySymbols() 返回对象的所有symbol属性 注意:symbol相对特殊,是ES6+之后才有的,早期JS中的对象只有字符串key,所以前两个方法主要针对字符串key

说到这我总想穿插一句,for(const key in o) for in可以穿透遍历到原型上的属性。

js
const sym = Symbol()
o[sym] = 'sym'
Object.defineProperty(o, 'a', {
    enumerable: false,
    value: '123'
})
console.log(Object.keys(o)) // ['name']
console.log(Object.getOwnPropertyNames(o)) // ['name', 'a']
console.log(Object.getOwnPropertySymbols(o)) // [Symbol()]

console.log(Reflect.ownKeys(o)) // ['name', 'a', Symbol()]

定义对象的属性

  • Object.getOwnPropertyDescriptor():获取某个属性的描述对象。
  • Object.defineProperty():通过描述对象,定义某个属性, 包括enumerable configurable writablevalue 与 get set,不展开说了。
  • Object.defineProperties():通过描述对象,定义多个属性。

控制对象的状态

  • Object.preventExtensions():防止对象扩展(添加新属性)。
  • Object.isExtensible():判断对象是否可扩展。
  • Object.seal():阻止其扩展并且使得现有属性不可配置。
  • Object.isSealed():判断一个对象是否可配置。
  • Object.freeze():冻结一个对象。
  • Object.isFrozen():判断一个对象是否被冻结。

几个描述的详细解释:

  • extensible: 可拓展,即可添加新属性
  • seal: 密封,不可拓展、不能删除现有属性或更改其可枚举性和可配置性、不能重新分配其原型。
  • freeze: 冻结,密封,且属性不可写,

Object的实例方法

  • Object.prototype.valueOf():返回当前对象对应的值,一般就是自身,参与类型转换。
  • Object.prototype.toString():返回当前对象对应的字符串形式,参与类型转换,可用于判断数据类型
  • Object.prototype.toLocaleString():返回当前对象对应的本地字符串形式。
  • Object.prototype.hasOwnProperty():判断某个属性是否为当前对象自身的属性,还是继承自原型对象的属性。
  • Object.prototype.isPrototypeOf():判断当前对象是否为另一个对象的原型。
  • Object.prototype.propertyIsEnumerable():判断某个属性是否可枚举。
js
// 利用 toString来判断类型

function type(o){
  var s = Object.prototype.toString.call(o);
  return s.match(/\[object (.*?)\]/)[1].toLowerCase();
};
type({}); // "object"
type([]); // "array"
type(5); // "number"
type(null); // "null"
type(); // "undefined"
type(/abcd/); // "regex"
type(new Date()); // "date"

属性描述符对象

JS 提供了一个内部数据结构,用来描述对象的属性,控制它的行为,比如该属性是否可写、可遍历等等。这个内部数据结构称为“属性描述对象”(attributes object)。每个属性都有自己对应的属性描述对象,保存该属性的一些元信息

  • value
  • writable
  • enumerable
  • configurable
  • get/set

不再多说了,注意几个地方:

  1. Cannot both specify accessors and a value or writable attribute
    一旦定义了取值或存值函数get/set,就不能将writable属性设为true,也不能同时定义value属性,否则会报错。

  2. get无参,set一个参

  3. for...in 循环包括继承的属性