一:object.defineProperty的缺点:
1.因为es5的object.defineProperty无法监听对象属性的删除和添加
2.不能监听数组的变化,除了push/pop/shift/unshift/splice/spObject.definert/reverse,其他都不行
3.Object.defineProperty只能遍历对象属性直接修改(需要深拷贝进行修改)
二:proxy的优点:
1.直接监听对象而非属性
2.直接监听数组的变化
3.拦截的方式有很多种(有13种,set,get,has)
4.proxy返回一个新对象,可以操作新对象达到目的
三:proxy的缺点:
proxy有兼容性问题,不能用polyfill来兼容(polyfill主要抚平不同浏览器之间的对js实现的差异)
四:实现vue3双向绑定
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <div></div> <script> const toProxy = new WeakMap(); //存放的是代理后的对象 const toRaw = new WeakMap(); //存放的是代理前的对象 function trigger() { console.log('触发视图更新') } function isObject(target) { return typeof target === 'object' && target !== null; } function reactive(target) { if (!isObject(target)) { return target; } let proxy = toProxy.get(target) // 如果代理表中已经存在了 就把这个结果返回 if (proxy) { return proxy } // 如果这个对象已经被代理过了 就直接返回 if (toRaw.has(target)) { return target; } const handlers = { set(target, key, value, receiver) { if (target.hasOwnProperty(key)) { trigger() } return Reflect.set(target, key, value, receiver) }, get(target, key, value, receiver) { const res = Reflect.get(target, key, receiver) if (isObject(target[key])) { return reactive(res) } return res; }, deleteProperty(target, key) { return Reflect.deleteProperty(target, key) } } let observed = new Proxy(target, handlers) toProxy.set(target, observed); toRaw.set(observed, target) return observed } let obj = { name: '温小鹿', arr: [1, 2, 3] } // let p = reactive(obj) // p.name = 'jw' // let arr = [1, 2 ,3]; // let p = reactive(arr) // p.push(4); // console.log(p) let p = reactive(obj) p = reactive(p) p = reactive(p) p.arr.push(4) console.log(p) </script> </body> </html>