对象和属性
JS中,对象是键值对的集合。这些值是对象的属性,它可以是一个基本类型或对象,也可以是方法(method)。
比如:
const Person = { name: 'Brynn', greet: function () { console.log('Hello I am', this.name) }, }
上面这个对象有一个name基本类型,和一个greet方法。
用上面这种定义方法是最简单的,称为用字面量定义。
除此之外,还可以用Object.defineProperty()
来配置一个属性,用Object.getOwnPropertyDescripter()
查询配置具体情况。
所以,上面的代码可以写成:
const Person = {} Object.defineProperty(Person, 'name', { value: 'Brynn', writable: true, enumerable: true, configurable: true, }) Object.defineProperty(Person, 'greet', { value: function () { console.log('Hello I am', this.name) }, writable: true, enumerable: true, configurable: true, })
特性
在Object.defineProperty
中出现了一些属性(property
)的特性(attribute
),这些特性如下:
- value: 属性的值
- writable: 是否可修改属性的value
- enumerable: 是否可枚举(只有可枚举的属性才能同构
Object.keys(target)
以及for in
获取,可枚举和不可枚举的都可以通过Object.getOwnPropertyNames(target)
获取) - configurable:是否可修改属性的attribute,只有可配置属性的才能被delete删除
- set: 写入属性时调用的函数(使用Brynn.name = ‘Boolean’就会调用set函数)
- get:获取属性时调用的函数(使用console.log(Brynn.name)就会调用get函数)
这些特性不能同时全部存在于一个属性上,根据这一点的不同,又将属性分为数据属性和访问器属性
- 数据属性:有
value/writable/enumerable/configurable
四个特性 - 访问器属性: 有
set/get/enumerable/configurable
四个特性
Object.defineProperty()
set和get的用法如下
const Person = { _name: 'abc', } // Object.defineProperty(Person, 'name', { // value: 'Brynn', // writable: true, // enumerable: true, // configurable: true, // }) Object.defineProperty(Person, 'name', { set: function (value) { if (value.match(/[bB]rynn/)) this._name = value }, get: function () { return this._name }, enumerable: true, configurable: true, }) console.log('setter属性', Object.getOwnPropertyDescriptor(Person, 'name'))
{ set: undefined, get:undefined, writable:false, enumerable:false, configurable:false }
当使用字面量直接定义时,这些特性的默认值不同:
{ writable:true, enumerable:true, configurable:true }
getter和setter
getter/setter很类似于Object.defineProperty()的访问器属性
Getter/setter
let Person = { _name: 'abc', set name(value) { console.log(' setter函数里面调用this', this) if (value.match(/[bB]rynn/)) this._name = value }, get name() { console.log(' getter里面调用this', this) return this._name }, } console.log('使用setter定义的name属性', Object.getOwnPropertyDescriptor(Person, 'name')) console.log('Person对象(person)', Person) console.log('Person对象自己的属性(Object.getOwnPropertyNames):', Object.getOwnPropertyNames(Person))
let Person = { _name: 'abc', } Object.defineProperty(Person, 'name', { set: function (value) { console.log('set函数里面调用this', this) if (value.match(/[bB]rynn/)) this._name = value }, get: function () { console.log(' getter里面调用this', this) return this._name }, // enumerable: true, // configurable: true, }) console.log('使用setter定义的name属性', Object.getOwnPropertyDescriptor(Person, 'name')) console.log('Person对象(person)', Person) console.log('Person对象自己的属性(Object.getOwnPropertyNames):', Object.getOwnPropertyNames(Person))
区别是
- 用defineProperty添加属性更灵活,可以动态添加
- 特性的默认值不同,defineProperty的默认值是false,setter/getter的默认值是true
自身属性和原型属性
对象属性做遍历的时候,会用到的方法有for in
和for of
- for in:遍历自身和原型链上的所有可枚举属性,返回的是键
- for