Getter/Setter之深入浅出,对象属性监听

在我们实际项目中,有可能会遇到监听一个对象的属性变化(当然,全局变量可以看做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

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

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值