微信号:ardays

介绍:android每日绝对干货

详解Object.defineProperty()

2017-11-28 13:49 kai

前言

Object.defineProperty是ES5新增的一个API,其作用是给对象的属性增加更多的控制。在我们日常的coding中,这个API用到的地方不多,然而它对于MVVM框架中双向数据绑定(two-ways data binding)来说是至关重要的一个API,目前vue和avalon中的双向数据数据绑定均是通过它来实现的。

使用

Object.defineProperty方法提供了一种直接的方式来定义对象属性或者修改已有对象属性。

语法

1
Object.defineProperty(obj, prop, descriptor)

参数

obj: 需要定义属性的对象(目标对象)

prop: 需被定义或修改的属性名(对象上的属性或者方法)

descriptor: 需被定义或修改的属性的描述符

descriptor

objprop都比较好理解,我们重点来解析第三个参数属性描述符,它是一个对象,里面有以下取值:

value: 属性的值

1
2
3
4
5
6
7
var a = {}

Object.defineProperty(a, 'b', {
value: 2
})

console.log(a.b); // => 2

writable: 属性是否能被重写(rewrite),默认为false

1
2
3
4
5
6
7
8
9
10
11
12
var a = {}

Object.defineProperty(a, 'b', {
value: 2,
writable: false
})

console.log(a.b); // output 2

a.b = 3

console.log(a.b); // still ouput  2

enumerable: 属性是否能在for ... in或者Object.keys中被枚举出,来默认为false

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var a = {}

Object.defineProperty(a, 'b', {
value: 2,
enumerable: false
})

console.log(Object.keys(a)) // output []

Object.defineProperty(a, 'c', {
value: 2,
enumerable: true
})

console.log(Object.keys(a)) // output ['c']

configurable: 是否能够配置valuewritableconfigurable,默认为false

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var a = {}

Object.defineProperty(a, 'b', {
value: 2,
enumerable: false
})

console.log(a.b) // output 2

Object.defineProperty(a, 'b', {
value: 3,
enumerable: true
})

// TypeError: Cannot redefine property: b

get: 一个给属性提供 getter 的方法,默认undefined

set: 一个给属性提供 setter 的方法,默认undefined

属性描述符分为数据描述符和存取描述符。数据描述符是一个拥有可写或不可写值的属性。存取描述符是由一对 getter-setter 函数功能来描述的属性。

数据描述符和存取描述符均具有可选键值:configurableenumerable

数据描述符同时具有可选键值:value,writable,get,set

用思维导图来表示就是:

get/set

对于setget,我的理解是它们是一对勾子(hook)函数,当你对一个对象的某个属性赋值时,则会自动调用相应的set函数;而当获取属性时,则调用get函数。这也是实现双向数据绑定的关键。

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
var a = {}
var b

Object.defineProperty(a, 'b', {
get: function() {
console.log('get b')

// 我们可以在这里对返回的值做任何操作
return b + 1
},
set: function(newValue) {
console.log('set b to', newValue)
b = newValue
}
})

a.b = 100

console.log(a.b);

/*
output:
 set b to 100
 get b
 101
*/

注意

数据描述符和存取描述符不能混合使用

1
2
3
4
5
6
7
8
9
Object.defineProperty(o, "conflict", {
 // value是数据描述符
 value: 1,
 // get是存取描述符
 get: function() {
   return 2;
 }
});
// throws a TypeError: value appears only in data descriptors, get appears only in accessor descriptors



 
Android每日干货 更多文章 探索ES2015:箭头函数(Arrow Functions) 微信浏览器踩坑集锦 好久不见 三句代码完成整个App侧滑关闭 慢慢的我也会失去自己
猜您喜欢 向《番茄工作法图解》作者Staffan Nöteberg提问!| 问题征集 涨姿势!一篇文读懂交互设计基础 投票:你认为《过往记忆》博客内容咋样 又想先拍再吃 数据告诉你美食图片的真相! 大公司如何体制内创新?(3)