对象的概念
对象是Javascript中一个极其重要的概念,可以说Javascript中万物皆对象。对象可以将多个相关联的数据封装到一起,以便更好地表述一个事物。
- 比如我们要描述一辆车:Car,那么它有哪些数据呢?
大小(size),品牌(brand),价格(price),高度(height)等等。 所以我们可以将这些信息抽象成一个对象来表达:
const Car = {
brand: 'Benz',
size: 'large',
price: '1,000,000',
height: '1.8'
}
那么创建一个Javascript对象有哪几种方式呢?有两种方式:
new创建- 字面量创建
Object.create创建
// new创建
const obj1 = new Object()
obj1.name = 'zengge'
obj1.age = 22
// 字面量创建
const obj2 = {}
obj2.name = 'zengge'
obj2.age = 22
// Object.create
const newObj = Object.create (null, {
name: {
value: 'zengge',
enumerable: true
},
age: {
value: 22,
enumerable: true
}
})
其实这三种方法创建对象并没有什么很大的区别,因为第二种字面量创建对象写法简单而且易读,所以我们更推荐第二种写法。
对象的操作
首先最常见的对象操作就是增删改查了
const obj = {
name: 'zengge',
age: 22
}
// 增加属性
obj.size = 'large'
// 删除属性
delete obj.size
// 修改属性
obj.name = 'zengdada'
// 查看属性
console.log(obj.name)
如果我们现在想要对obj对象进行更加精准的控制,比如不允许某一个属性被赋值或者不允许某一个属性被遍历,那么应该怎么办呢?我们需要用到Object.defineProperty。
Object.defineProperty(obj, prop, descriptor)
可以接收三个参数:
- obj是要定义的对象
- prop是要定义或者修改的属性的名称或者
Symbol- descriptor要定义或修改的
属性描述符我们提到了属性描述符,什么是属性描述符?属性描述符(Property Descriptor)是 ES5 之后出现的概念,顾名思义,它用于描述属性应该是什么样,例如是否只读,能否枚举,能否可配置等。所有对象属性均可使用属性描述符来定义。 属性描述符的类型有两种:
数据属性(Data Properties)描述符存取属性(Accessor Properties)描述符
数据属性描述符
数据属性有4个描述其行为的特性:
- 可配置性
[[Configurable]]: 表示能否通过delete删除属性,能否修改属性特性,能否把数据属性修改为访问器属性。 - 可枚举性
[[Enumerable]]:表示能否通过for-in循环返回属性。 - 可写入性
[[Writable]]:表示能否修改属性值。 - 属性值
[[Value]]:表示属性值。 这样说会有点抽象,我们来写一段代码来解释一下:
可配置性[[Configurable]]
const obj = {
name: 'zengge',
age: 22
}
Object.defineProperty(obj, 'size', {
value: 'large', // 设置值
configurable: false // 不可配置,也就是说不可删除和不可修改
})
for(let i in obj) {
console.log(i)
}
console.log(Object.keys(obj))
delete obj.age
console.log(obj.age)
delete obj.size
console.log(obj.size)
我们看到这里删除age属性成功,而删除size属性失败了,依然打印出了large。
可枚举性[[Enumerable]]
const obj = {
name: 'zengge',
age: 22
}
Object.defineProperty(obj, 'size', {
value: 'large', // 设置值
enumerable: true // 不可枚举,for-in无法遍历属性,Object.key也无法遍历属性
})
for(let i in obj) {
console.log(i)
}
console.log(Object.keys(obj))
可以看到size属性并没有被遍历出来,因为我们将enumerable设置为true。
可写入性[[Writable]]
const obj = {
name: 'zengge',
age: 22
}
Object.defineProperty(obj, 'size', {
value: 'large', // 设置值
writeable: false // 不可修改,不能写入新值
})
obj.size = 'small'
console.log(obj.size)
我们尝试修改obj的size为small,但是失败了,size依然是large,因为我们配置了writeable为false。
存取属性描述符
存取属性描述符是由一对 getter-setter 函数功能来描述的属性,如下图代码:
const obj = {
name: 'zengge',
age: 22,
_size: 'large'
}
Object.defineProperty(obj, 'size', {
enumerable: true,
configurable: false,
get: function() {
return this._size
},
set: function(value) {
this._size
}
})
这样的话我们外部如果要获取size属性或者修改size属性,那么会经过get和set函数,可以在这回两个函数中进行额外的操作。注意当存在存取属性描述符时,数据属性描述符的value值是不可以设置的,这样会导致报错。