js中挺重要的一个api,vue2的数据劫持也是基于此。
Object.defineProperty 会直接在对象上定义一个新的属性,或者修改一个现有属性。语法如下:
1  | Object.defineProperty(obj, key, descriptor)  | 
- obj:将要被修改的对象
 - key:将要被修改对象的名称或者symbol
 - descriptor:对象的描述符。此函数的核心点
下面是为对象foo添加一个新的属性b的例子:1
2
3
4
5
6
7const foo = {a: 1}
console.log(foo.a) // 1
console.log(foo.b) // undefined
Object.defineProperty(foo, 'b', {
value: 2
})
console.log(foo.b) // 2 
描述符
对象一共存在 6种 描述符,configurable、enumerable、value、writeable、get、set。
这6种描述符,并不是可以随意组合使用。 value或writeable不能够和get或set同时使用,编译会报错。
描述符可以分为两类:数据描述符和存取描述符,如下展示不同描述符可以使用的键值:  
| configurable | enumerate | value | writable | get | set | |
|---|---|---|---|---|---|---|
| 数据描述符 | yes | yes | yes | yes | no | no | 
| 存取描述符 | yes | yes | no | no | yes | yes | 
configurable
default:false
决定属性是否可以被修改
如果旧值设置为false,只能够单向改变writable为false
enumerable
default:false
决定是否可以被Object.keys和for..in枚举
value
default:undefined
可以是任何有效地js值(数值,对象,函数等)
writable
default:false
只有设置为true时,上面的value值才可以被改变
get
default:undefined
属性的 getter 函数,如果没有 getter,则为 undefined。当访问该属性时,会调用此函数。执行时不传入任何参数,但是会传入 this 对象(由于继承关系,这里的this并不一定是定义该属性的对象)。该函数的返回值会被用作属性的值。
set
default:undefined
属性的 setter 函数,如果没有 setter,则为 undefined。当属性值被修改时,会调用此函数。该方法接受一个参数(也就是被赋予的新值),会传入赋值时的 this 对象。