介绍
js语言总是有些璀璨的珍珠,等待人们去挖掘,比如defineProperty, 这里主要介绍他的getter和setter,在vue中使用的比较多,这个方法很神奇,赋予了数据"劫持"的功能,那么同样ES6中的Proxy也是赋予数据"劫持"的功能,所以vue3.0想用Proxy来进一步升级vue...感觉带"劫持"功能的都很牛x的感觉...axios?...router guards...我劫..我劫..我打劫...
emmmmm....这里也不写太多了,就了解并使用一下defineProperty吧
示例
例1. 一个proxy函数
const noop = function() {}const sharedPropertyDefinition = { enumerable: true, configurable: true, get: noop, set: noop}// 定义一个proxy函数function proxy (target, sourceKey, key) { sharedPropertyDefinition.get = function proxyGetter() { return this[sourceKey][key] } sharedPropertyDefinition.set = function proxySetter(val) { this[sourceKey][key] = val } Object.defineProperty(target, key, sharedPropertyDefinition)}let obj = { info: { age: 20 }}// 调用proxy函数proxy(obj, 'info', 'age')// 这样可以通过obj.age来访问obj.info.age属性了// 20console.log(obj.age)// 再来尝试使用obj.age来修改obj.info.ageobj.age = 30// { age: 30, info: { age: 30 } }console.log(obj)复制代码
例2. 了解一下 -- 同一属性多个defineProperty会实行覆盖
即此例并不会输出set1, get1let obj = { age: 20}Object.defineProperty(obj, 'age', { get() { console.log('get1') }, set() { console.log('set1') }})Object.defineProperty(obj, 'age', { get() { console.log('get2') }, set() { console.log('set2') }})// 输出set2obj.age = 30// 输出get2console.log(obj.age)复制代码
例3. 了解一下 -- 对象子属性修改并不会触发上一层属性的setter
let stu = { info: { name: 'jinyong', age: 20 }}let info = stu['info']let name = info.nameObject.defineProperty(stu, 'info', { get() { console.log('get1') return info }, set(newVal) { console.log('set1') info = newVal }})Object.defineProperty(info, 'name', { get() { console.log('get2') return name }, set(newVal) { console.log('set2') name = newVal }})// 输出 get1 及 输出 set2,但并不会输出set1stu.info.name = 'jinyong100'复制代码
看例4前了解下以下情况,这样操作不会修改stu.info的,不解释了
let stu = { info: { name: 'jinyong', age: 80 }} function test123(info) { info = { name: 'jinyong', age: 30 }}test123(stu.info)复制代码
例4. 结合proxy以及为对象子属性设置access property(即getter, setter)
执行vm.info.name = 'jinyong100'
时会输出get1, get2, set3
console.log(vm.info.name)
时会输出get1, get2, get3, jinyong100 应该能理解输出的结果吧。 let vm = { _data: { info: { name: 'jinyong' } }}// 相当于proxy(vm, '_data', 'info')Object.defineProperty(vm, 'info', { get() { console.log('get1') return this['_data']['info'] }, set(newVal) { console.log('set1') this['_data']['info'] = newVal }})let info = vm._data.info// 由于例2中的情况,虽然我们使用vm.info成功代理vm._data.info了// 我们还是要defineProperty vm._data对象而不是vm对象Object.defineProperty(vm._data, 'info', { get() { console.log('get2') return info }, set(newVal) { console.log('set2') info = newVal }})// 由于例3中的情况,如果值也是一个对象,那么对其每个属性也要definePropertylet name = info.nameObject.defineProperty(info, 'name', { get() { console.log('get3') return name }, set(newVal) { console.log('set3') name = newVal }})vm.info.name = 'jinyong100'console.log(vm.info.name)复制代码