本文解析JavaScript中常规对象与异质对象的本质区别,阐述[[Get]]与[[Call]]内部方法的作用。重点讲解Proxy如何通过拦截器透明代理对象,并结合Reflect操作原始对象,揭示其底层工作原理及在Vue3中的应用基础。
正文
本章内容虽属JavaScript基础科普,但鉴于本书读者通常已非入门级别,按理无需重复此类知识。然而作者仍特意安排此章,旨在揭示JavaScript对象概念中那些容易被误解或忽视的独特之处。
JavaScript中一切皆对象
这句话广为人知。对于常规的字面量对象和使用new关键字创建的对象,读者通常能够清晰区分。
const str = ''
const str2 = new String()
const obj = {}
const obj2 = Object.create()
然而,根据ECMA规范,JavaScript中的对象实际上分为两类:常规对象和异质对象。任何不属于常规对象范畴的均被归类为异质对象。
在JavaScript体系中,函数同样被视为一种对象。当我们访问Obj.foo时,实际上是在调用对象内部的[[Get]]方法以获取该值。ECMA规范中定义了如下内部方法(见网图)。因此

由此可见,普通对象必须拥有一组被称为基本内部方法(essential internal methods)的默认行为,即上图所示内容。若这些默认方法被修改,则该对象即转变为异质对象。
例如Array,当我们执行Array.lenght = 0时,数组内容会被清空。
看到这张图后,判断一个变量是普通对象还是函数的关键在于:它使用的是[[Get]]还是[[Call]]。
毫无疑问,Proxy属于异质对象,它可以直接修改某些默认方法。当我们在Proxy中未定义Get拦截器时,它会调用对象内部自身的[[Get]],从而实现代理的透明性。
这段文字我反复研读许久才理解其真意。实际上,Proxy并不会直接更改对象内部的原有方法和行为,而是通过指定需要代理的具体方法来实现拦截功能,这也与Proxy的使用方式相吻合。
const p = new Proxy(obj,{/*被代理的属性*/})
此时,p与obj是完全不同的对象,拥有独立的内存地址。这意味着我们无法直接在p上操作obj,此时必须借助反射Reflect。反射如同一面镜子,映射出原始对象的地址,我们通过对原始对象obj进行操作,而非直接操作p。
前两章介绍了关于Proxy和Reflect的基础理论,下一章将具体讲解Vue3如何利用Proxy进行开发。
以上即为JavaScript对象及Proxy工作原理详解的详细内容,更多关于JavaScript对象Proxy的资料请关注本站其它相关文章!