💻 【Javascript】数据劫持(代理)详解 🏠专栏:Javascript
👀个人主页:繁星学编程🍁
🧑个人简介:一个不断提高自我的平凡人🚀
🔊分享方向:目前主攻前端,其他知识也会阶段性分享🍀
👊格言:☀️没有走不通的路,只有不敢走的人!☀️
👉让我们一起进步,一起成为更好的自己!!!🎁
文章目录
- 【Javascript】数据劫持(代理)
- 一. Object.defineProperty()
- 二. 数据劫持
- 三. 封装函数实现数据劫持
- 四. 数据代理(Proxy)
- 五. Proxy和Object.defineProperty的区别
【Javascript】数据劫持(代理)
所谓数据代理(也叫数据劫持),指的是在访问或者修改对象的某个属性时,通过一段代码拦截这个行为,进行额外的操作或者修改返回结果。比较典型的是 Object.defineProperty()
和 ES2015 中新增的 Proxy
对象。而在前端框架中vue2.0使用的是Object.defineProperty()
、vue3.0使用的是Proxy
。当然今天主要讲述的JS和ES中的数据劫持,vue中的小编后续会安排上。
一. Object.defineProperty()
语法:Object.defineProperty(数据, 属性名, {配置项})
配置项:
-
value:设置属性名对应的属性值
-
writable:设置的属性是否可以修改
值:true/false(默认)
-
enumerable:设置的属性是否可以遍历
值:true/false (默认)
-
configurable:设置的属性是否可以删除
值:true/false(默认)
-
getter、setter:不允许和value, writable连用,连用会报错
- get 获取的时候可以触发的方法
- set 设置的时候可以触发的方法
注:value、writable、enumerable、configurable可以单独使用也可以连用
针对上述配置项的使用情况:
(1) value
const obj = { name: "zs" }
Object.defineProperty(obj, "age", {
value: 20;
});
console.log(obj);
obj.age = 30;
console.log(obj);
(2) writable
const obj = { name: "zs" }
Object.defineProperty(obj, "age", {
writable: true
})
console.log(obj);
obj.age = 30;
console.log(obj);
(3) enumerable
const obj = { name: "zs" }
Object.defineProperty(obj, "age", {
value: 20,
enumerable: true
});
for (let k in obj) {
console.log(k, obj[k]);
}
(4) configurable
const obj = { name: "zs" }
Object.defineProperty(obj, "age", {
configurable: true
});
delete obj.name;
console.log(obj);
(5) get set定义属性
const obj = { name: "zs" }
Object.defineProperty(obj, "age", {
get() {
return 20;
},
set(val) {
console.log(val);
}
});
obj.age = 19;
console.log(obj.age);
console.log(obj);
二. 数据劫持
当访问或者修改对象的某个属性的时候,通过 getter setter 拦截这个行为,进行额外的操作
将原始的数据复制一份,通过复制的数据操作原始数据
<div id&#61;"box"></div>
<input type&#61;"text" id&#61;"ipt1">
<input type&#61;"text" id&#61;"ipt2">
<!-- 分割线 -->
const obj &#61; {
name: &#39;zs&#39;,
age: 20
}
const target &#61; {}
Object.defineProperty(target, &#39;name&#39;, {
get() {
return obj.name
},
set(val) {
obj.name &#61; val
box.innerHTML &#61; &#96;你好&#xff0c; 我叫${target.name} , 我今年${target.age}&#96;
}
})
Object.defineProperty(target, &#39;age&#39;, {
get() {
return obj.age
},
set(val) {
obj.age &#61; val
box.innerHTML &#61; &#96;你好&#xff0c; 我叫${target.name} , 我今年${target.age}&#96;
}
})
box.innerHTML &#61; &#96;你好&#xff0c; 我叫${target.name} , 我今年${target.age}&#96;
ipt1.onchange &#61; function () {
target.name &#61; this.value
}
ipt2.onchange &#61; function () {
target.age &#61; this.value
}
三. 封装函数实现数据劫持
<div id&#61;"box">div>
<input type&#61;"text" id&#61;"ipt1">
<input type&#61;"text" id&#61;"ipt2">
<script>
const obj &#61; {
name: &#39;zs&#39;,
age: 20
}
function encapsulation(obj, cb) {
let target &#61; {};
for (let k in obj) {
Object.defineProperty(target, k, {
get() {
return obj[k];
},
set(val) {
obj[k] &#61; val;
cb(target);
}
});
}
cb(target);
return target;
}
let app &#61; encapsulation(obj, (target) &#61;> {
box.innerHTML &#61; &#96;你好&#xff0c; 我叫${target.name} , 我今年${target.age}&#96;;
});
ipt1.onchange &#61; function () {
app.name &#61; this.value;
}
ipt2.onchange &#61; function () {
app.age &#61; this.value;
}
script>
效果图&#xff1a;
四. 数据代理(Proxy)
在数据劫持这个问题上&#xff0c;Proxy
可以被认为是 Object.defineProperty()
的升级版。外界对某个对象的访问&#xff0c;都必须经过这层拦截。因此它是针对 整个对象&#xff0c;而不是 对象的某个属性&#xff0c;所以也就不需要对 keys
进行遍历。
Proxy 对象用于创建一个对象的代理&#xff0c;从而实现基本操作的拦截和自定义&#xff08;如属性查找、赋值、枚举、函数调用等&#xff09;。
语法&#xff1a;
const p &#61; new Proxy(target, handler)
参数&#xff1a;
-
target
要使用 Proxy
包装的目标对象&#xff08;可以是任何类型的对象&#xff0c;包括原生数组&#xff0c;函数&#xff0c;甚至另一个代理&#xff09;。
-
handler
一个通常以函数作为属性的对象&#xff0c;各属性中的函数分别定义了在执行各种操作时代理 p
的行为。
简单的数据代理案例&#xff1a;
const obj &#61; {
name: &#39;tom&#39;,
age: 18
}
const res &#61; new Proxy(obj, {
get(target, property) {
return target[property];
},
set(target, property, val) {
target[property] &#61; val;
return true;
}
})
res.name &#61; &#39;jerry&#39;;
res.sex &#61; &#39;女&#39;;
console.log(&#39;原始数据&#39;, obj);
console.log(&#39;代理结果&#39;, res);
五. Proxy和Object.defineProperty的区别
- Proxy是对整个对象的代理&#xff0c;而Object.defineProperty只能代理某个属性。
- 对象上新增属性&#xff0c;Proxy可以监听到&#xff0c;Object.defineProperty不能。
- 数组新增修改&#xff0c;Proxy可以监听到&#xff0c;Object.defineProperty不能。
- 若对象内部属性要全部递归代理&#xff0c;Proxy可以只在调用的时候递归&#xff0c;而Object.definePropery需要一次完成所有递归&#xff0c;性能比Proxy差。
- Proxy不兼容IE&#xff0c;Object.defineProperty不兼容IE8及以下
- Proxy使用上比Object.defineProperty方便多。
结束语&#xff1a;
希望对您有一点点帮助&#xff0c;如有错误欢迎小伙伴指正。
&#x1f44d;点赞&#xff1a;您的赞赏是我前进的动力&#xff01;
⭐收藏&#xff1a;您的支持我是创作的源泉&#xff01;
✍评论&#xff1a;您的建议是我改进的良药&#xff01;
一起加油&#xff01;&#xff01;&#xff01;&#x1f4aa;&#x1f4aa;&#x1f4aa;