JS关于数据代理_Object.defineProperty_Vue数据代理_双向绑定
作者:互联网
defineProperty == 给对象定义属性用的
需要传递三个基本参数
- 需要定义属性的对象名
- 你要定义的属性叫什么名字(比如给person这个实体添加一个age属性)
- 配置项(对象类型的参数,里面存放键值对)
![image-20221021165746534](https://wavesbright-typora.oss-cn-shenzhen.aliyuncs.com/typora/Vue/image-20221021165746534.png)
<script>
// 创建一个对象,该对象有两个基本属性
var person = {
name:"张三",
sex:"男"
}
// 为person对象添加属性
// 1、给那个对象添加?
// 2、添加的属性名是什么?
// 3、这个属性的基础配置项(对象类型,键值对形式)
Object.defineProperty(person,"age",{
value:18, // 该属性的值是
})
</script>
需求1
- 给 对象person,添加一个属性age,有几种方式?
- 三种
- 直接在 person对象当中添加属性;该属性值可以修改
- 通过 .属性;对其设置;该属性值可以修改
- 通过 Object.finedProperty()进行添加;该属性值不可枚举(不可修改) 默认情况下
- 直接在 person对象当中添加属性;该属性值可以修改
不可枚举性
通过 defineProperty添加的属性
![image-20221021234243445](https://wavesbright-typora.oss-cn-shenzhen.aliyuncs.com/typora/Vue/image-20221021234243445.png)
如果不设置配置项,那么该属性是不可枚举的;在控制台中可以看到,颜色变浅了
![image-20221021234337336](https://wavesbright-typora.oss-cn-shenzhen.aliyuncs.com/typora/Vue/image-20221021234337336.png)
该属性不参与遍历,我们可以测试下
![image-20221021234502785](https://wavesbright-typora.oss-cn-shenzhen.aliyuncs.com/typora/Vue/image-20221021234502785.png)
基本配置项
value
最开始配置的
![image-20221021234533851](https://wavesbright-typora.oss-cn-shenzhen.aliyuncs.com/typora/Vue/image-20221021234533851.png)
enumerable
![image-20221021234759192](https://wavesbright-typora.oss-cn-shenzhen.aliyuncs.com/typora/Vue/image-20221021234759192.png)
Object.defineProperty(person,"age",{
value:18, // 该属性的值是
enumerable:true, // 该配置项控制添加的属性是否参与枚举
})
writable
设置属性是否可以被修改
![image-20221021235042150](https://wavesbright-typora.oss-cn-shenzhen.aliyuncs.com/typora/Vue/image-20221021235042150.png)
configurable
控制属性是否可以被删除
没有通过函数添加age属性的person对象
![image-20221021235630870](https://wavesbright-typora.oss-cn-shenzhen.aliyuncs.com/typora/Vue/image-20221021235630870.png)
通过函数添加age属性的person对象删除属性
![image-20221021235852707](https://wavesbright-typora.oss-cn-shenzhen.aliyuncs.com/typora/Vue/image-20221021235852707.png)
设置配置项删除掉age属性
![image-20221022000003394](https://wavesbright-typora.oss-cn-shenzhen.aliyuncs.com/typora/Vue/image-20221022000003394.png)
需求2
- 准备一个变量 number,值为18
- person当中有一个age属性,这个属性的value 是 number(不是手写的18)
![image-20221022000349813](https://wavesbright-typora.oss-cn-shenzhen.aliyuncs.com/typora/Vue/image-20221022000349813.png)
问题所在
- 这个变量的值可能会发生改变,如果呢?
- 修改number,person对象当中的age值并没有发生改变
- 同理,修改age,number也不会发生改变
这俩好像有点关系,但好像又没有关系,就js代码加载的时候这俩自顶而下有了这一层关系,但也仅仅只有这一层
![image-20221022000643083](https://wavesbright-typora.oss-cn-shenzhen.aliyuncs.com/typora/Vue/image-20221022000643083.png)
那怎么完成这个需求呢?
![image-20221022000850459](https://wavesbright-typora.oss-cn-shenzhen.aliyuncs.com/typora/Vue/image-20221022000850459.png)
请看下方的高级配置项
高级配置项
get(getter)配置项
![image-20221022084643923](https://wavesbright-typora.oss-cn-shenzhen.aliyuncs.com/typora/Vue/image-20221022084643923.png)
解析
- 它的数据类型是一个对象
- 当 有人读取 person当中的age属性的时候,get就会被调用
- 且get的返回值就是age 的 value值
- 自定义get(getter函数)的时候,不能再使用基础配置了
那 返回一个 waves 字符串吧
![image-20221022082755645](https://wavesbright-typora.oss-cn-shenzhen.aliyuncs.com/typora/Vue/image-20221022082755645.png)
三个点儿
- invoke:映射
- property:属性
- getter:get配置项 == 函数
- get是属性名
- 他的类型是一个函数类型
- 加在一起就是getter
![image-20221022082826309](https://wavesbright-typora.oss-cn-shenzhen.aliyuncs.com/typora/Vue/image-20221022082826309.png)
- age 属性 是有的
- 但是 value 是多少,目前不知道(...)
- 想知道怎么办?点进去嘛
![image-20221022083735374](https://wavesbright-typora.oss-cn-shenzhen.aliyuncs.com/typora/Vue/image-20221022083735374.png)
get函数
![image-20221022084142173](https://wavesbright-typora.oss-cn-shenzhen.aliyuncs.com/typora/Vue/image-20221022084142173.png)
写个代码测试一下,打印一句话
![image-20221022084453981](https://wavesbright-typora.oss-cn-shenzhen.aliyuncs.com/typora/Vue/image-20221022084453981.png)
![image-20221022084542759](https://wavesbright-typora.oss-cn-shenzhen.aliyuncs.com/typora/Vue/image-20221022084542759.png)
看样子是的,我前面的措辞有问题
number与age进行关联
![image-20221022085613352](https://wavesbright-typora.oss-cn-shenzhen.aliyuncs.com/typora/Vue/image-20221022085613352.png)
对number值进行修改
![image-20221022085734444](https://wavesbright-typora.oss-cn-shenzhen.aliyuncs.com/typora/Vue/image-20221022085734444.png)
那么对age修改呢?
![image-20221022085858395](https://wavesbright-typora.oss-cn-shenzhen.aliyuncs.com/typora/Vue/image-20221022085858395.png)
问题所在
- 一定是 先访问age
- 再调用getter
- 当number的value发生改变的时候
- 再次访问age,那么就重新调用了getter函数
- 重新调用getter,会返回number,而这个number是修改过的,所以这边数据是同步了
修改age;失败
![image-20221022090126038](https://wavesbright-typora.oss-cn-shenzhen.aliyuncs.com/typora/Vue/image-20221022090126038.png)
修改number,再访问age;成功
![image-20221022085734444](https://wavesbright-typora.oss-cn-shenzhen.aliyuncs.com/typora/Vue/image-20221022085734444.png)
set(setter)配置项
同理,既然有get,那么与之相辅相成的就是set
当你对age属性进行修改的时候,set(setter)函数就被调用
且,调用的时候,会收到具体修改的 值
/**
* 需要传递一个参数value
* 被调用的时候,会收到具体修改的值
*/
set(value){
// 当你对age属性进行修改的时候,set(setter)函数就被调用
// 被调用的时候,会收到具体修改的值
console.log("pseron.age属性发生修改,修改的值是",value);
}
测试
![image-20221022091237163](https://wavesbright-typora.oss-cn-shenzhen.aliyuncs.com/typora/Vue/image-20221022091237163.png)
实现双向绑定
- get函数
- 实现了 number 与 age 的绑定,number发生修改的时候,age会发生变化
- 当 age的值发生变化的时候,number值不变,所以无论怎么修改,age的值 === number
- set函数
- 实现了 age 与 number 的绑定,age的值发生变化的时候,number的值也会跟着变化
- set函数会接到 age所修改的value,将value 赋值 给 number,完成双向绑定
![image-20221022091606249](https://wavesbright-typora.oss-cn-shenzhen.aliyuncs.com/typora/Vue/image-20221022091606249.png)
测试
![image-20221022091937218](https://wavesbright-typora.oss-cn-shenzhen.aliyuncs.com/typora/Vue/image-20221022091937218.png)
总结
通过案例
- number 与 person,是两个东西
- 但是借助 Object.defineProperty,使二者进行了关联
- person,确实是一个对象,age确实是person当中的属性
- 但是值呢?你现用,我现去给你取
- 靠谁取? == get
- 靠谁改? == set
什么是数据代理?
定义
通过一个对象,代理对另一个对象,中属性的操作 (读/写 == get/set)
需求
- 我这里有两个对象,obj1 与 obj2;属性值如下
- obj1 可以 对自身的 属性 x进行修改,访问
- 现在我想让 obj2 也有这个功能 == obj2 可以访问 obj1 的 x,并且也能对 x 进行修改
实现
这就需要借助我们的defineProperty了
![image-20221022104222226](https://wavesbright-typora.oss-cn-shenzhen.aliyuncs.com/typora/Vue/image-20221022104222226.png)
<script>
var obj1 = {
x:100
}
var obj2 = {
y:200
}
// 为 对象obj2 添加一个属性x,实现双向绑定
Object.defineProperty(obj2,"x",{
// 当访问obj2的x属性时
get(){
// 实际上是将 obj1的 x 属性返回
return obj1.x;
},
// 当对 obj2的 x 属性进行修改的时候
set(value){
// 将收到的value值赋予给obj1的x属性即可
obj1.x = value;
}
})
</script>
测试
- obj1 与 obj2 身上是否都有x属性?
- 修改 obj2的x属性,obj1的x属性是否会发生变化?
- 上述案例就是个最基本的 数据代理