Skip to main content

对象

object 方法

1.object.defineProperty

Object.defineProperty(obj,props)

  • obj 在其上定义属性
  • props 属性的描述符
    • configurable: 属性是否可配置(指的是这个属性是否可以被删除和重新定义), 默认 false
    • enumerable: 是否可枚举, 默认 false
    • value: 属性值
    • writable: 是否可写, 默认 false
    • get: 读取属性值的时候调用的函数
    • set: 设置属性值的时候调用的函数
var obj = {}
Object.defineProperties(obj, {
isAdmin: {
value: true,
writable: true,
},
name: {
value: 'John',
writable: false,
},
age: {
configurable: true,
writable: true,
value: 11,
},
// etc. etc.
})
Object.defineProperties(obj, {
name: {
value: 'Tom',
writable: false,
},
}) //报错 不能重新定义
Object.defineProperties(obj, {
age: {
value: 1000,
writable: false,
},
}) //报错 不能重新定义
// name 不可写
// age 可以删除, isAdmin和name 不能重新定义和删除

2.object.create

创建一个指定原型对象的对象,

Object.create(proto,[propertiesObject])

  • proto 为新创建对象的原型
  • propertiesObject 为新创建对象的属性
const person = {
proto: 'aaa',
}

const me = Object.create(person)

me.name = 'Matthew'
me.isHuman = true
let obj = Object.create(null)
//创建一个纯净对象

ES6 新增

属性简洁表示

ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁。

const obj = {
f() {
this.foo = 'bar'
},
}

可枚举性

对象的每个属性都有一个描述对象(Descriptor),用来控制该属性的行为。Object.getOwnPropertyDescriptor 方法可以获取该属性的描述对象。

let obj = { foo: 123 }
Object.getOwnPropertyDescriptor(obj, 'foo')
// {
// value: 123,
// writable: true,
// enumerable: true,
// configurable: true
// }

引入“可枚举”(enumerable)这个概念的最初目的,就是让某些属性可以规避掉 for...in 操作,不然所有内部属性和方法都会被遍历到。比如,对象原型的 toString 方法,以及数组的 length 属性,就通过“可枚举性”,从而避免被 for...in 遍历到。

Object.getOwnPropertyDescriptor(Object.prototype, 'toString').enumerable
// false

Object.getOwnPropertyDescriptor([], 'length').enumerable
// false

目前,有四个操作会忽略 enumerable 为 false 的属性。

  • for...in 循环:只遍历对象自身的和继承的可枚举的属性。
  • Object.keys():返回对象自身的所有可枚举的属性的键名。
  • JSON.stringify():只串行化对象自身的可枚举的属性。
  • Object.assign(): 忽略 enumerable 为 false 的属性,只拷贝对象自身的可枚举的属性。

属性的遍历

  1. for..in..遍历

    for...in 循环遍历对象自身的和继承可枚举属性(不含 Symbol 属性)。

  2. Object.keys()

    返回一个数组,包括对象自身的(不含继承的)所有可枚举(不含 Symbol 属性的健名

  3. Object.getOwnPropertyNames(obj)

    Object.getOwnPropertyNames 返回一个数组,包含对象自身的所有属性(不含 Symbol 属性,但是包括不可枚举属性)的键名

  4. Object.getOwnPropertySymbols(obj)

    Object.getOwnPropertySymbols 返回一个数组,包含对象自身的所有 Symbol 属性的键名

  5. Reflect.ownKeys(obj) Reflect.ownKeys 返回一个数组,包含对象自身的(不含继承的)所有键名,不管键名是 Symbol 或字符串,也不管是否可枚举。

以上的 5 种方法遍历对象的键名,都遵守同样的属性遍历的次序规则。

  • 首先遍历所有数值键,按照数值升序排列。
  • 其次遍历所有字符串键,按照加入时间升序排列。
  • 最后遍历所有 Symbol 键,按照加入时间升序排列。

super

this 关键字总是指向函数所在的当前对象,ES6 又新增了另一个类似的关键字 super,指向当前对象的原型对象。

const proto = {
foo: 'hello',
}

const obj = {
foo: 'world',
find() {
return super.foo
},
}

Object.setPrototypeOf(obj, proto) //将obj的原型指向proto
obj.find() // "hello"

Object.is

ES6 提出“Same-value equality”(同值相等)算法,用来解决这个问题。Object.is 就是部署这个算法的新方法。它用来比较两个值是否严格相等,与严格比较运算符(===)的行为基本一致。 不同之处只有两个:一是+0 不等于-0,二是 NaN 等于自身

Object.is('foo', 'foo')
// true
Object.is({}, {}) +
// false

0 ===
-0 //true
NaN === NaN // false

Object.is(+0, -0) // false
Object.is(NaN, NaN) // true

Object.assign

  1. 克隆对象
function clone(origin) {
let originProto = Object.getPrototypeOf(origin)
return Object.assign(Object.create(originProto), origin)
}

ES6 原型链

// es5 的写法
const obj = {
method: function() { ... }
};
obj.__proto__ = someOtherObj;

// es6 的写法
var obj = Object.create(someOtherObj);
obj.method = function() { ... };

Object.fromEntries()

Object.fromEntries()方法是 Object.entries()的逆操作,用于将一个键值对数组转为对象。 该方法的主要目的,是将键值对的数据结构还原为对象,因此特别适合将 Map 结构转为对象。

Object.fromEntries([
['foo', 'bar'],
['baz', 42],
])
// { foo: "bar", baz: 42 }

对象的问题

1.Object.create()、new Object()和{}的区别