Object.defineProperty与 Proxy区别
- 所有属性监听
- Object.defineProperty无法一次性监听对象所有属性,必须遍历或者递归来实现
- Proxy的实现就不需要遍历
- Proxy 的get方法用于拦截某个属性的读取操作,可以接收三个参数,依次为目标、属性名和Proxy实例本身,其中最后一个参数为可选参数
- set方法用来拦截某个属性的赋值操作,可以接受四个参数,依次为目标对象、属性名、属性值和Proxy实本身,其中最后一个为可选参数
- 新增属性监听
Object.defineProPerty无法监听新增属性,如果需要监听新增属性,需要手动再做一次监听,在Vue中想动态监听属性,一般用Vue.set(对象实例, “新增对象属性”)这种形式来添加
Proxy可以监听新增属性
- 数组操作
Object.defineProperty 无法响应数组操作
可以监听数组变化,但无法对新增数组变化进行监听,因此Mobk中为了监听数组变化,默认将数组长度设置为1000,监听0-999的属性变化
如果想要监听push、shift、pop、unshift等方法,该怎么做?Vue和Mobx中都是通过重写原型的方法实现的:在定义变量的时候,判断是否是数组,如果是数组,那么就修改它的proto,将其指向subArrProto,从而实现重写原型链。
vue源码:
场景:
- 利用Proxy set get 应用proxy表单验证
1 | //验证规则 |
- get 用来拦截私有属性的读取, 用_ 开头的属性是私有属性, 禁止私有属性读取
1 | const person ={ |
- 等等还有其他Proxy的方法使用 …….(get/ set/ apply/ construct/ has/ delete/ delete)
- !!! Proxy 可以提高开发效率和代码质量,但在使用过程中需要注意性能优化、避免循环引用导致栈溢出、合理使用拦截器和兼容性等方面的细节。
展开运算符
[…arr]
支持展开运算符是要有Symbol.iterator
arr[Symbol.iterator]
面试题:
1 | //我们能否以某种方式为下面的语句使用展开运算而不导致类型错误 ? |
- 对象转数组案例
- 使用 Object.keys() 方法获取对象的所有键,然后使用 map() 方法将每个键对应的值存入新数组中。
1 | const obj = { a: 1, b: 2, c: 3 }; |
- 使用 Object.values() 方法获取对象的所有值,直接将值存入新数组中。
1 | const obj = { a: 1, b: 2, c: 3 }; |
- 使用 Object.entries() 方法获取对象的键值对数组,然后对每个键值对进行处理。
1 | const obj = { a: 1, b: 2, c: 3 }; |
1 | #### 高效运算符 '?.' 和 '??' 和 '??=' 的区别 |
- 其他
- 继承:通过原型链,我们可以实现对象之间的继承关系,子对象可以继承父对象的属性和方法。可以尝试创建一个新的构造函数,让它继承自
Person
构造函数,并添加新的属性或方法。 - 原型修改:可以尝试修改
Person
构造函数的原型对象上的方法,然后看看实例对象是否能够访问到修改后的方法。 - 原型链终止:在原型链的顶端是
Object.prototype
,它的原型是null
。可以思考一下为什么原型链的顶端是Object.prototype
,而不是其他对象。
- 继承:通过原型链,我们可以实现对象之间的继承关系,子对象可以继承父对象的属性和方法。可以尝试创建一个新的构造函数,让它继承自