Object.defineProperty()
MDN上的解释是Object.defineProperty()会直接在对象上定义一个新的属性,或者修改一个对象的现有属性,并返回这个对象。
###在ECMAScript中属性有两种
数据属性
数据属性包含一个数据值的位置,在这个位置可以读取和写入值,数据属性有四个描述其行为的特性
- [[Configurable]] : 表示能否通过delete删除属性从而重新定义属性,默认为true
- [[Enumerable]] : 表示能否通过for-in循环返回属性,默认为true
- [[Writable]] : 表示能否修改属性的值,默认为true
- [[Value]] : 属性的数据值,默认值为undefined
访问器属性
访问器属性不包含数据值;它包含一对getter和setter函数(这两个函数都不是必须的,也不需要成对出现),在读取访问其属性时,会调用getter函数,这个函数负责返回有效的值,在写入访问器属性时,会调用setter函数并传入新值,这个函数负责决定如何处理数据。在这里让我想起了vue中也有一个getter和setter,vue的双向绑定就是通过object.defineProperty()完成的。
- [[Configurable]] : 表示能否通过delete删除属性从而重新定义属性,默认为true
- [[Enumerable]] : 表示能否通过for-in循环返回属性,默认为true
- [[Get]] : 在读取属性时调用的函数,默认为undefined
- [[Set]] : 在读取属性时调用的函数,默认值为undefined
通常我们创建一个对象,可以用构造函数或者字面量的形式,当然除了这些还有很多方式如原型模式、工厂模式、构造函数和原型的组合方式等等
1 | var obj = new Object; //obj = {} |
###Object.defineProperty(obj, prop, descriptor)
参数:
- obj: 目标对象
- prop: 需要定义或修改的属性名字
- descriptor: 目标属性所拥有的特性
返回值:
- 传入函数的对象,即第一个参数obj
####针对Configurable、Writable特性
1 | var person = {} |
这个例子创建了一个名为name的属性,但是这个属性是只读的,不可修改。而在configurable为false时,该属性不能被删除。同时在严格模式下,如果尝试给它赋予新值将会抛出错误。
####针对Get、Set特性
1 | var book = { |
以上代码创建了一个book对象,并给它定义了两个属性, _ year 和 edition。_year前面的下划线表示该属性只能被对象方法访问的属性,是一种常用的记号。这是使用访问器的常用方式,即设置一个属性的值会导致其他属性发生变化。
###此外
记我一次见过的面试题
==利用给定接口获得闭包的对象==
1 | var o = (function() { |
Q: 在不改变上面代码的情况下,怎么得到原有的person对象?
A:
1 | Object.defineProperty(object.prototype, 'self', { |