Object.defineProperty初体验
首先是 MDN 的解释:
Object.defineProperty()
方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象。
对于 Object.defineProperty
早有耳闻,比如 Vue
就依赖此方法来实现数据响应。最近在 ajax-hook 中也发现了此方法的身影,于是也来探体验一番。
试验代码
const cat = {
name: 'Tom',
age: 3
}
const testObj = {}
// configurable enumerable writable 都为 true
testObj.name = 'Jack'
// configurable enumerable writable 都为默认值 false
Object.defineProperty(testObj, 'age', {
value: 8
})
console.log(Object.getOwnPropertyDescriptor(testObj, 'name'))
console.log(Object.getOwnPropertyDescriptor(testObj, 'age'))
// delete testObj.name // true
// delete testObj.age // false
Object.defineProperty(testObj, 'someObj', {
value: {
num: 1
},
enumerable: true,
configurable: true,
writable: false
})
simpleSet(cat, 'name', 'nick')
simpleSet(testObj, 'str', 'test')
simpleSet(testObj, 'other', 'writable')
simpleSet(testObj, 'age', 18) // error
// testObj.age = 3 // not changed
// testObj.someObj = { num: 3 } // not changed
// testObj.someObj.num = 3 // changed..
// testObj.other = 3 // changed
console.log('cat', cat)
console.log('testObj', testObj)
// 不包含 age 属性
console.log('all of the properties', Object.keys(testObj)) // or use `for in`
// 返回一个由指定对象的所有自身属性的属性名组成的数组
// `包括不可枚举属性`,不包括Symbol值作为名称的属性
console.log('getOwnPropertyNames', Object.getOwnPropertyNames(testObj))
function simpleSet(obj, key, val) {
let value = val
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get: function() {
console.log('getter:', key, value)
return value
},
set: function(v) {
console.log('setter:', key, v)
value = v
}
})
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
在 Chrome Console 中的样子
几个比较重要的点:
- value 与 get, set 不可共存
- 一旦使用
Object.defineProperty
来定义属性,未配置的描述符将为默认值,与直接赋值不同 Object.defineProperty
可以重新定义configurable
为true
的属性