Object.defineProperty和Proxy
Object.defineProperty
概述
Object.defineProperty()
方法用于在指定对象上定义一个新属性,或者修改一个对象的现有属性,并 返回该对象 。( 原地更改对象 )
语法
Object.defineProperty(obj, prop, descriptor)
obj
:要在其上定义属性的对象。prop
:要定义或修改的属性的名称。descriptor
:一个包含属性描述符的对象,决定属性的特征。
属性描述符descriptor
属性描述符是一个对象,包含以下可选键:
value
:属性的值。writable
:如果为true
,属性的值可以被赋值操作改变。get
:一个函数,当属性被读取时调用,函数返回值就是属性的值。set
:一个函数,当属性被赋值时调用,接收赋值操作传入的值。configurable
:如果为true
,属性可以被删除,get
和set
访问器可以被修改。enumerable
:如果为true
,表示可以遍历,属性出现在for...in
循环中。
示例
1 | const obj = { |
1 | const obj = { |
注意事项
get
和set
访问器中this
关键字指向定义属性的上下文,通常是一个属性描述符对象,而不是目标对象。- 属性必须是
configurable: true
才能被Object.defineProperty()
修改或使用delete
删除。
Proxy
概述
Proxy
对象用于创建一个对象的代理,从而在访问对象前可以进行某种操作。
语法
new Proxy(target, handler)
target
:一个对象,它是代理对象的原始对象。handler
:一个对象,其属性是当操作代理对象时定义代理的行为的函数。
处理程序(Handler)
处理程序对象可以定义以下11个方法:
注意:receiver
参数是 Reflect.get
方法的第三个可选参数,它的作用是:
- 当你访问的对象属性实际上是通过原型链从另一个对象继承的访问器属性(即有一个
getter
函数)时,**receiver
参数指定了调用这个getter
函数时this
应该指向的对象。**
在大多数简单的情况下,你可能不需要使用 receiver
参数,因为默认情况下,访问器属性的 getter
会在访问它的那个对象上被调用。
但是,如果你需要确保在访问继承的访问器属性时,this
绑定到特定的对象上,那么 receiver
参数就非常有用了。
1 | const parent = { |
get(target, prop, receiver)
:获取属性时调用。set(target, prop, value, receiver)
:设置属性时调用。has(target, prop)
:检查属性是否存在时调用。deleteProperty(target, prop)
:删除属性时调用。ownKeys(target)
:获取对象所有键时调用。getOwnPropertyDescriptor(target, prop)
:获取属性描述符时调用。defineProperty(target, prop, descriptor)
:定义属性时调用。preventExtensions(target)
:阻止对象扩展时调用。getPrototypeOf(target)
:获取对象原型时调用。isExtensible(target)
:检查对象是否可扩展时调用。setPrototypeOf(target, proto)
:设置对象原型时调用。
示例
1 | const obj = { |
1 | const obj = { |
注意事项
- 代理对象的
delete
、deleteProperty
、has
、set
和defineProperty
操作可以拦截对象的相应操作。 - 代理可以创建一个对象的“安全”版本,隐藏内部的实现细节。
- 代理可以用于懒加载或延迟初始化对象的属性。
对比 Object.defineProperty
和 Proxy
Object.defineProperty
用于在对象上定义或修改单个属性。Proxy
可以用于整个对象,为对象的所有操作提供自定义行为。Object.defineProperty
实现对象的深度监听,需要一次性递归到底。对于层级比较深的数据来说,计算量比较大。Object.defineProperty
无法监听新增属性/删除属性, 因为监听在created
之前就完成了。(但是vue2.0提供了另外的api,分别是Vue.set和Vue.delete)Proxy
可以监听新增属性/删除属性等。- 使用
Object.defineProperty
可以修改对象的现有属性(就地更改),而Proxy
允许你从头开始捕获和自定义任何操作。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 灰太羊的羊村!
评论
ValineDisqus