GetterSetter之深入浅出,对象属性监听

    xiaoxiao2021-03-25  106

    在我们实际项目中,有可能会遇到监听一个对象的属性变化(当然,全局变量可以看做window对象的属性)而执行某些操作。get/set分别对属性的获取/赋值进行监听斌并执行某些操作。

    对于cookie应该都不陌生,它执行document.cookie='a=1'的时候并不会覆盖原来的cookie,而是覆盖原来的a的值或则追加一个a。当然,这里cookie是不是通过getter/setter来实现的不做深究,我们就拿实现一个类似的对象来作为例子。

    初始化声明

    var test = { _cookie: '', get cookie() { console.log('get cookie'); return this._cookie; }, set cookie(val) { console.log('set cookie: ' + val); // TODO 对_cookie和val进行判断是否有某个值再进行追加或则覆盖操作。 // 字符串的操作这里就不多写了 this._cookie = val; return val; } } test.cookie; // get cookie '' 这里执行了get的函数 test.cookie = 1; // set cookie 1 1 这里执行了set的函数

    注意,这里值是存在_cookie里面而不是cookie里面的。因为如果还是存在cookie属性里面当set的时候我们会去执行this.cookie = val,这样又会去执行set,就会无限循环了。

    defineGetter/defineSetter

    对于某些已经存在的对象我们无法直接在声明的时候声明getter/setter,可以使用这两个函数进行操作。例如作为window属性的全局变量。

    var _test = ''; window.__defineGetter__('test', function(){ console.log('get test'); return this._test; }); window.__defineSetter__('test', function(val) { console.log('set test'); // TODO 某些操作 this._test = val; return this._test; }); test; // get test '' test = 2; // set test 2

    注意,这个方法不再推荐使用,这里拿出来只是见见而已,而且某些浏览器貌似不再至此这玩意了。ES5添加了新的方法。

    defineProperty/defineProperties

    defineProperty/defineProperties不只是对于get/set的声明,同时还能添加/修改对象属性特性描述(可枚举、可修改、可设置),有兴趣的可以去看看对象属性描述,本文不做详解。

    var _test = ''; Object.defineProperty(window, 'test', { get(){ console.log('get test'); return this._test; }, set(val){ console.log('set test'); // TODO 某些操作 this._test = val; return this._test; } }); test; // get test '' test = 2; // set test 2

    Object.defineProperties只是对defineProperty的扩展,一次性添加/修改多个对象属性特性描述。

    var _a = '', _b = ''; Object.defineProperties(window, { a: { get(){ console.log('get a'); return this._a; }, set(val){ console.log('set a'); // TODO 某些操作 this._a = val; return this._a; } }, b: { get(){ console.log('get b'); return this._b; }, set(val){ console.log('set b'); // TODO 某些操作 this._b = val; return this._b; } } }); a; // get a '' b; // get b '' a = 1; // set a 1 b = 1; // set b 1

    注意,defineProperty/defineProperties都是Objet的方法,操作对象作为第一个参数传入。

    扩展

    如果只是对对象属性的监听,ES6提供了更加高级的类—Proxy(代理)。直接监听所有对象的所有属性,而且不用申明_xxx。

    var obj = new Proxy({}, { get: function (target, key, receiver) { console.log('get ' + key); return Reflect.get(target, key, receiver); }, set: function (target, key, value, receiver) { console.log('set ' + key + ':' + value); return Reflect.set(target, key, value, receiver); } }); obj.a = 1; // set a:1 obj.b = 2; // set b:2

    当然,这么牛逼的玩意肯定不会只有这点作用,具体可以自己去研究。

    转载请注明原文地址: https://ju.6miu.com/read-5136.html

    最新回复(0)