Vue中的ECMAScript①-为什么选用Proxy?
内部方法
在ECMAScript中,每个对象内部都有一系列不暴露给程序员的内部方法。对象不同,内部方法也会不同,但每个对象都会包含一系列必要的内部方法:
内部方法 | 签名 | 描述 |
---|---|---|
[[GetPrototypeOf]] | ( ) → Object / Null | 获取该对象继承的对象 返回null:没有继承属性 相当于getPrototypeOf() |
[[SetPrototypeOf]] | (Object / Null) → Boolean | 为该对象关联原型 参数null:没有继承属性 返回true:操作成功 返回false:操作失败 相当于setPrototypeOf() |
[[IsExtensible]] | ( ) → Boolean | 判断是否允许向该对象添加其他属性 返回true:允许 返回false:不允许 相当于isExtensible() |
[[PreventExtensions]] | ( ) → Boolean | 判断该对象当前是否能添加属性 返回true:能 返回false:不能 如果返回false,即使[[IsExtensible]]为true,添加新属性操作也会失败 相当于preventExtensions() |
[[GetOwnProperty]] | (propertyKey) → Undefined | Property Descriptor | 返回此对象自身属性的属性描述符 如果没有对应的属性,返回undefined 相当于getOwnPropertyDescriptor() |
[[DefineOwnProperty]] | (propertyKey, PropertyDescriptor) → Boolean | 创建或更改自己的属性 参数propertyKey:属性名 参数PropertyDescriptor:属性描述符 返回true:操作成功 返回false:操作失败 相当于defineOwnProperty() |
[[HasProperty]] | (propertyKey) → Boolean | 判断此对象是否有或继承某一属性 参数propertyKey:属性名 返回true:有或继承该属性 返回false:没有且不继承该属性 相当于has() / in关键字 |
[[Get]] | (propertyKey, Receiver) → any | 根据属性名返回对象中的属性值 参数propertyKey:属性名 参数Receiver:按ES规范,它会被当作this来用。 相当于get() / 读取操作 |
[[Set]] | (propertyKey, value, Receiver) → Boolean | 将参数value 设置为对象中属性名为参数propertyKey 的值参数Receiver:被当作this用 返回true:操作成功 返回false:操作失败 相当于set() / 赋值操作 |
[[Delete]] | (propertyKey) → Boolean | 根据属性名删除对象中的属性 参数propertyKey:属性名 返回true:删除成功 返回false:删除失败 相当于deleteProperty() / delete关键字 |
[[OwnPropertyKeys]] | ( ) → List of propertyKey | 返回对象自己的所有属性键 相当于ownKeys() |
还有两个函数特有的内部方法:[[Call]]和[[Construct]]
这些内部方法是多态的,对象不同,其内部的实现也可能不同
对象
JavaScript一切皆对象,分为常规对象和异质对象两种对象,任何不属于常规对象的都是异质对象
区分不同对象的方法就是看它们的内部方法和内部槽
常规对象必须满足以下三点要求:
- 必要内部方法根据ECMA规范10.1.x的定义实现
- [[Call]]根据ECMA规范10.2.1的定义实现
- [[Construct]]根据ECMA规范10.2.2的定义实现
Proxy
Proxy当然也算一种对象,它的内部实现与普通对象不同,所以它是一个异质对象
例如[[Get]]在Proxy的实现:创建Proxy对象时,如果指定了Get()拦截函数,则为拦截函数,否则为普通对象的[[Get]]
也就是说,Proxy其实就是用来自定义对象行为的
Vue2中使用属性描述符的getter和setter函数,也能满足响应式,但它存在很多反直觉的缺陷,例如新增的属性必须要经过额外处理才能成为响应式、数组本身无法响应必须调用重写的数组方法
而Vue3中使用Proxy,接近JavaScript的底层,那么只需要观察ECMAScript里对一些操作的实现,确定其用到的对象内部方法,就可以有针对性的编写适合它的响应式逻辑了
评论