深入理解 Getter和Setter 对对象的属性监听
阅读目录
- 一:理解普通对象在声明时添加 get、set
- 二:Object.prototype.__defineGetter__ 和 Object.prototype.__defineSetter__
- 三:Object.defineProperty
- 四:Object.defineProperties
- 五:Proxy
一:理解普通对象在声明时添加 get、set
在做vue的时候,我们经常会看到 data里面的属性 都有 get 和 set方法,如下所示:
如上vue中data里面它有两个属性,一个xxx 数组 和 一个 testA对象,但是都有get和set方法。也就是说在vue中data里面的每个属性都有两个相对应的get和set方法。为什么会有这样的呢?下面我们先来看一个普通的对象,如下代码所示:
const obj = {
name: 'kongzhi',
_age: 30,
get age() {
return this._age;
},
set age(x) {
this._age = x;
}
}; console.log(obj);
打印会如下所示:
当我们继续打印如下信息:
console.log(obj._age); // 输出:30
console.log(obj.age); // 输出:30 // 设置值
obj.age = 31; console.log(obj.age); // 输出:31 console.log(obj.age()); // Uncaught TypeError: obj.age is not a function
如上代码演示所示,我们在对象里面使用 get 或 set定义的 age, 它只是obj中的一个属性,它并不是方法,因此如上我们使用获取属性的值或设置属性的值操作是正常的,当我们使用 obj.age() 把它当做一个方法调用的时候,它会报错。因此在vue中所有的属性有get、set这样的,当我们自动给某个属性赋值的时候,它会自动调用 set对应的方法,当我们获取某个属性的时候,它会自动调用get方法。但是我们不能手动调用 set/get xxx() 中的xxx这样的方法。
二:Object.prototype.__defineGetter__ 和 Object.prototype.__defineSetter__
上面只是在声明obj对象的时候,编写get和set 对应的属性。但是如果已经存在的对象的时候,再想继续添加 get/set呢?那只有使用
Object.prototype.__defineGetter__ 和 Object.prototype.__defineSetter__ 了,如下代码演示:
const obj = {
name: 'kongzhi',
_age: 30
}; obj.__defineGetter__('age', function(){
console.log('监听到正在获取属性age的值');
return this._age;
}); obj.__defineSetter__('age', function(value) {
console.log('监听到正在设置属性age的值为:' + value);
this._age = value;
}); /*
* 打印:监听到正在获取属性age的值
* 输出:30
*/
console.log(obj.age); // 打印:监听到正在设置属性age的值为:31
obj.age = 31; /*
* 打印:监听到正在获取属性age的值
* 输出: 31
*/
console.log(obj.age);
但是呢?Object.prototype.__defineGetter__ 和 Object.prototype.__defineSetter__ 这个方法已经不推荐使用了,并且随着以后浏览器的发展,可能会不再支持该方法,那怎么办呢?当然会有新的替代方案的,我们继续往下讲。
三:Object.defineProperty
该方法它是由两部分组成,分别是:数据描述符和访问器描述符,数据描述符的含义是:它是一个包含属性的值,并说明这个属性值是可读或不可读的对象。访问器描述符的含义是:包含该属性的一对 getter/setter方法的对象。
那么具体项了解该方法的使用及详解,请看我这篇文章(https://www.cnblogs.com/tugenhua0707/p/10261170.html),下面看使用 Object.defineProperty 来监听对象属性值的变化,如下代码:
const obj = {
name: 'kongzhi',
_age: 30
};
Object.defineProperty(obj, 'age', {
get() {
console.log('监听到正在获取属性age的值');
return this._age;
},
set(value) {
console.log('监听到正在设置属性age的值为:' + value);
this._age = value;
return this._age;
}
}); /*
* 打印:监听到正在获取属性age的值
* 输出:30
*/
console.log(obj.age); // 打印:监听到正在设置属性age的值为:31
obj.age = 31; /*
* 打印:监听到正在获取属性age的值
* 输出: 31
*/
console.log(obj.age);
四:Object.defineProperties
Object.defineProperties 是对 Object.defineProperty的扩展的,它可以一次性添加多个/修改多个对象属性描述符。
如下代码演示:
const obj = {
_name: 'kongzhi',
_age: 30
};
Object.defineProperties(obj, {
age: {
get() {
console.log('监听到正在获取属性age的值');
return this._age;
},
set(value) {
console.log('监听到正在设置属性age的值为:' + value);
this._age = value;
return this._age;
}
},
name: {
get() {
console.log('监听到正在获取属性name的值');
return this._name;
},
set(value) {
console.log('监听到正在设置属性name的值为:' + value);
this._name = value;
return this._name;
}
}
});
/*
* 打印:监听到正在获取属性age的值
* 输出:30
*/
console.log(obj.age); // 打印:监听到正在设置属性age的值为:31
obj.age = 31; /*
* 打印:监听到正在获取属性age的值
* 输出: 31
*/
console.log(obj.age); console.log('-------下面是对象name属性的监听-------');
/*
* 打印:监听到正在获取属性name的值
* 输出:kongzhi
*/
console.log(obj.name); // 打印:监听到正在设置属性name的值为:longen
obj.name = 'longen'; /*
* 打印:监听到正在获取属性name的值
* 输出: longen
*/
console.log(obj.name);
五:Proxy
那么具体了解Proxy是啥,是干啥使用的,请看我这篇文章(https://www.cnblogs.com/tugenhua0707/p/10306793.html);
那么它也可以监听对象属性值的变化,如下代码演示:
const target = {
name: 'kongzhi'
}; const handler = {
get: function(target, key) {
console.log(`${key} 被读取`);
return target[key];
},
set: function(target, key, value) {
console.log(`${key} 被设置为 ${value}`);
target[key] = value;
}
}; const testObj = new Proxy(target, handler); /*
获取testObj中name属性值
会自动执行 get函数后 打印信息:name 被读取 及输出名字 kongzhi
*/
console.log(testObj.name); /*
改变target中的name属性值
打印信息如下: name 被设置为 111
*/
testObj.name = 111; console.log(target.name); // 输出 111
深入理解 Getter和Setter 对对象的属性监听的更多相关文章
- vue2.x版本中Object.defineProperty对象属性监听和关联
前言 在vue2.x版本官方文档中 深入响应式原理 https://cn.vuejs.org/v2/guide/reactivity.html一文的解释当中,Object.defineProperty ...
- vue对象属性监听
对象属性监听的两种方法: 1.普通的watch data() { return { frontPoints: 0 } }, watch: { frontPoints(newValue, oldValu ...
- vue watch关于对象内的属性监听
vue可以通过watch监听data内数据的变化.通常写法是: data: { a: 100 }, watch: { a(newval, oldVal) { // 做点什么... console.lo ...
- Android 向Application对象添加Activity监听
可以建立对象把Application.ActivityLifecycleCallbacks接口中的函数实现,并利用public void registerActivityLifecycleCallba ...
- 使用MutationObserver对象封装一个监听DOM生成的函数
(function(win){ 'use strict'; var listeners = []; var doc = win.document; var MutationObserver = win ...
- Vue2实践computed监听Vuex中state对象中的对象属性时发生的一些有趣经历
今天想实现一个功能,在全局中随时改变用户的部分信息.这时候就想到了用Vuex状态控制器来存储用户信息,在页面中使用computed来监听用户这个对象.看似一个很简单的逻辑,就体现了我基本功的不扎实呀. ...
- vue2之对象属性的监听
对象属性监听的两种方法: 1.普通的watch data() { return { frontPoints: 0 } }, watch: { frontPoints(newValue, oldValu ...
- Event 对象的属性和方法
事件触发时,会将一个 Event 对象传递给事件处理程序,比如: document.getElementById("testText").addEventListener(&quo ...
- 理解defineProperty以及getter、setter
我们常听说vue是用getter与setter实现数据监控的,那么getter与setter到底是什么东西,它与defineProperty是什么关系,平时有哪些用处呢?本文将为大家一一道来. 对象的 ...
随机推荐
- loj#6033. 「雅礼集训 2017 Day2」棋盘游戏(二分图博弈)
题意 链接 Sol 第一次做在二分图上博弈的题..感觉思路真是清奇.. 首先将图黑白染色. 对于某个点,若它一定在最大匹配上,那么Bob必胜.因为Bob可以一直沿着匹配边都,Alice只能走非匹配边. ...
- MMU学习总结
待完善 一.MMU主要完成哪些事务? 二.PowerPC上的BAT.LAW是做什么用的? 三.
- android开发——Android开发中的47个小知识
1.判断sd卡是否存在 boolean sdCardExist = Environment.getExternalStorageState().equals(android.os.Environme ...
- 浅谈SnackBar(Toast大兄弟)
SnackBar是 Android Support Library 22.2.1 里面新增提供的一个控件,我们可以简单的把它理解成一个加强版的Toast,或者是一个轻量级的Dialog. 特点: .S ...
- Tomcat映射虚拟路径到指定磁盘(eclipse)
用WangEditor富文本编辑,上传图片的时候,本文主要记录一下Tomcat映射虚拟路径到指定磁盘,保存到指定路径中,且能实现页面预览. 在实现之前wangeditor的简单实用请参照博主小道仙的后 ...
- mac下编译node源码
看过一篇win7 64x下面编译node的文章,链接地址:编译nodejs及其源码研究 下面学习一下在mac下面如何编译node源码. 过程也挺简单. 1.下载源码. > mkdir nodes ...
- sql 语句按字段指定值排序及分页
为特定字段赋值并排序 表[Table_temp]中列[col1]为字符,属性为varchar(),排序时需要按照B.A.C的顺序显示,则可按照以下SQL语句: select * from Table_ ...
- xtrabackup部署以及使用
简介 备份mysql数据库一直是一个比较恶心的工作,主要就是备份的数据库比较大实在是慢.最近开始使用xtrabackup来备份数据库,速度上快了很多,尤其还原速度要快的多.下面我将从安装开始简要介绍一 ...
- 浏览器本地数据存储解决方案以及cookie的坑
本地数据存储解决方案以及cookie的坑 问题: cookie过长导致页面打开失败 背景: 在公司的项目中有一个需求是打开多个工单即在同一个页面中打开了多个tab(iframe),但是需要在刷新时只刷 ...
- C# 隐藏最大化、最小化和关闭三个按钮
在Windows的窗体编程中,基本上每一个窗体都是一个最小化.最大化和关闭按钮的. 一.禁用最大化和最小化 对于最大化和最小化按钮,在C#窗体开发时,各一个属性来启用或禁用这两个按钮. this.Ma ...