深入理解 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是什么关系,平时有哪些用处呢?本文将为大家一一道来. 对象的 ...
随机推荐
- BZOJ2746: [HEOI2012]旅行问题(AC自动机 LCA)
Time Limit: 30 Sec Memory Limit: 256 MBSubmit: 1188 Solved: 383[Submit][Status][Discuss] Descripti ...
- loj#2483. 「CEOI2017」Building Bridges(dp cdq 凸包)
题意 题目链接 Sol \[f[i], f[j] + (h[i] - h[j])^2 + (w[i - 1] - w[j]))\] 然后直接套路斜率优化,发现\(k, x\)都不单调 写个cdq就过了 ...
- 申请Office 365一年免费的开发者账号攻略(2018年10月份版本)
要进行Office 365开发,当然需要有完整的Office 365环境才可以.为了便于广大开发人员快速地启动这项工作,微软官方给所有开发人员提供了免费的一年开发者账号 那么如何申请Office ...
- 导入MySQL数据库提示"Unknown character set: 'utf8mb4'"错误
错误提示:导入MySQL数据库提示"Unknown character set: 'utf8mb4'"错误 分析: 看来是因为数据库版本的问题导致的,之前网站MYSQL5. ...
- JMeter 线程组之ConcurrencyThreadGroup介绍
线程组之ConcurrencyThreadGroup by:授客 QQ:1033553122 测试环境 apache-jmeter-3.2 jmeter-plugins-manager-1.3.jar ...
- ImportError: No module named simplejson.scanner
一.出现ImportError: No module named simplejson.scanner,是没有安装simplejson,安装一下就好了. 安装指令:python setup.py in ...
- 接口的绑定方案和动态SQL
1. 接口绑定方案 MyBatis中, 提供了一套接口绑定方案. 程序员可以提供一个接口, 然后提供对应接口的一个mapper.xml文件. MyBatis会自动将接口和xml文件进行绑定. 实际上就 ...
- mysql练习----Using Null
teacher id dept name phone mobile 101 1 Shrivell 2753 07986 555 1234 102 1 Throd 2754 07122 555 1920 ...
- oracle USING 用法
提问 using(xx)中可以接多个列吗? using(xx)中的列可以接表名或别名吗? 在使用using的语句中,select * 可以使用吗? 如果表有别名t,select t.* from ta ...
- JavaScript -- 时光流逝(二):js中数组的方法
JavaScript -- 知识点回顾篇(二):js中数组的方法 1. 数组 (1)定义数组,数组赋值 <script type="text/javascript"> ...