《JavaScript高级程序设计》这本书比较厚,之前刚学JS的时候挑战过一次,结果止步第三章。现在工作了一段时间想想还是得回过头来补充一下基础知识的。目前刚看完第六章,就从第六章开始总结吧,再逐步补充之前的好了。
理解对象
该章节讲解了JS中对象的属性类型以及对象属性间的一些设置。
JS中的对象是什么
- JS中的对象只是一堆属性和值的无序集合,值的类型包括基本类型,函数,或者对象。
- 属性和值之间的关系是映射关系,遵循
key: value
的规范。
如何创建对象
JS中创建对象的方法非常简单,有两种:
- 使用
Object
构造函数
let a = new Object()
a.name = 'oxc'
console.log(a) // {name: "oxc"}
当然,你也可以在Object构造函数中传入一个参数,然后创建出来的对象是原始数据类型对象。
let a = new Object(1) // Number {[[PrimitiveValue]]: 1}
console.log(a) // 1
typeof a // 'object'
- 使用对象字面量创建对象
let a = {
name: 'oxc'
}
console.log(a) // {name: "oxc"}
对象的属性类型
该章节介绍了JS对象属性的类型及其特点,其中属性类型分为了数据属性和访问器属性两种,同时介绍了定义属性特征值的api: defineProperty()
和defineProperties
,以及读取对象属性特征值的api: getOwnerPropertyDescriptor()
。
- 对象属性的特征值
- 介绍:
对象属性的特征值是对象的属性的一些特性,可以在定义该属性的时候进行设置,但是在JS中是不能直接对其进行访问的。 - 分类
-
configurable
: 表示该属性是否能够被关键词delete
删除并进行重新定义,以及该属性的特性和属性类型能否被修改; -
enumerable
: 设置该属性能否被for-in
循环遍历到; -
writable
: 设置该属性的值能否被修改; -
value
: 设置该属性的值; -
get
: 访问该属性的时候执行的函数; -
set
: 对该属性的值进行设置的时候执行的函数;
-
- 介绍:
- 关于
Object.defineProperty
和Object.defineProperties
这两个api的作用就是用来设置上面的对象属性特征值的-
Object.defineProperty
该api用于设置单个对象属性的特征值,接受三个参数,顺序是需要设置属性特征值的对象,需要设置的属性,然后是特征值,使用示例如下
-
let a = {}
Object.defineProperty(a, 'name', {
configurable: true,
enumerable: true,
writable: true,
value: 'oxc'
})
console.log(a) // {name: 'oxc'}
-
Object.defineProperties
该api和defineProperty
作用一致,但是可以批量设置对象属性特征值,示例如下:
let a = {}
Object.defineProperties(a, {
name: {
value: 'oxc',
writable: false
},
age: {
value: 12,
writable: false
}
})
console.log(a) // {name: "oxc", age: 12}
- 对象的属性类型(数据属性和访问器属性)
- 数据属性
- 介绍: 对象的数据属性只标明数据值的位置,在该位置可以对值进行访问和写入。
- 数据属性包含的特征值有:
configurable
,enumerable
,writable
,value
- 如何定义一个数据属性:
- 数据属性
let a = {}
Object.defineProperty(a, 'name', {
configurable: false,
enumerable: false,
writable: false,
value: 'oxc'
})
console.log(a) // {name: 'oxc'}
// 该例子创建了一个名为name的属性,该属性可以被delete删除,for-in循环无法遍历它,也无法对其值进行修改,他的值为`oxc`,并且也不可以在下面对其属性特征值进行重写,重写特征值不会有任何反应。
// 该属性就是数据属性,值得一提的是,用对象字面量或者对象构造函数新建的对象属性`configurable`,`writable`,`enumerable`三个值默认都为true
- 访问器属性
- 介绍: 访问器属性是指通过这个属性去对象的属性;
- 访问器属性包含的特征值有:
configrable
,enumerable
,get
,set
; - 定义一个访问器属性
let a = {
_name: 'oxc'
}
Object.defineProperty(a, 'name', {
configurable: false,
enumerable: true,
get() {
return this._name
},
set(value) {
this._name = value
}
})
// 这时候我们可以通过调用a.name来对_name属性进行访问和写入,并且可以在访问和写入的过程中通过get和set做一些手脚,例如我想通过name读取到的是123,可以在get函数中这么写
get(){ return 123 }
console.log(a.name) // 123
// 又或者我想别人无论怎么设置a.name, a._name都是123,就可以在set函数中这么写
set(value){ this._name = 123 }
// 另外值得一提的是,如果enumerable设置为true, 那么访问器属性name也是可以可以被for-in循环遍历到的
- 访问器属性的用途
访问器属性除了上面所说的功能,在实际中的用途也是很广的,其中用得最多的一条就是用get
和set
函数通过计算对目标对象的其它属性进行修改,如下例子:
let a = {
_name: 'oxc',
age: 10
}
Object.defineProperty(a, 'name', {
configurable: false,
enumerable: true,
get() {
return this._name
},
set(value) {
value === '大春春' ? this.age = 80 : this.age = 10
}
})
a.name = '大春春'
console.log(a) // {_name: "oxc", age: 80}
值得一提的是,当前Vue的响应式系统的原理就是利用
Object.defineProperty
进行设置的,关于这点可以查看我的这篇博客关于Vue的MVVM
-
关于属性特征默认值
- 如果使用普通的对象创建方法创建的对象,就是不使用
Object.defineProperty
和Object.defineProperties
创建的属性,那么默认是数据属性,并且configurable
,enumerable
,'writable'都是true
- 但是如果使用的是
Object.defineProperty
和Object.defineProperties
创建的数据属性,那么configurable
,enumerable
,'writable'都是false
,访问器属性一样默认configurable
和enumerable
都为false
- 如果使用普通的对象创建方法创建的对象,就是不使用
// 普通创建的对象属性特征值
let a = {
name: 'oxc'
}
let b = Object.getOwnPropertyDescriptor(a, 'name')
console.log(b) // {value: "oxc", writable: true, enumerable: true, configurable: true}
// 使用Object.defineProperty创建的属性
let a = {}
Object.defineProperty(a, 'name', {
value: 'oxc'
})
let b = Object.getOwnPropertyDescriptor(a, 'name')
console.log(b) // {value: "oxc", writable: false, enumerable: false, configurable: false}
读取属性的特性
读取属性的特征值可以用Object.getOwnPropertyDescriptor
, 该方法接受两个参数,第一个参数是需要读取的属性所在的对象,第二个是需要读取的属性,例子如上默认值例子。