数据劫持
定义:数据劫持,指的是在访问或者修改对象的某个属性时,通过一段代码拦截这个行为,进行额外的操作或者修改返回结果。
其实就是一种给对象添加属性的方法
就是复刻一份对象 ,原来的对象是普通对象。原来的对象通过Object.defineProperty 设置一遍,会有一个新的对象,那么这个对象就是被监听的对象
方法一语法:
Object.defineProperty(obj,props,descriptor)
obj:必需。目标对象
prop:必需。需定义或修改的属性的名字
descriptor:必需。目标属性所拥有的特性
Object.defineProperty(obj,props,{
配置项
value:设置的值,
writable:表示是否允许被修改 默认false,
enumerable:表示是否允许被枚举(遍历) 默认false,
get(){},
set(){}
})
get:是一个函数,称之为获取器 getter。在访问这个属性的时候才会触发get方法,函数的返回值会作为该属性的值返回
注:不能和value 还有writable 一起使用
set:是一个函数,设置器setter。在改变这个属性的时候触发,而且能监听想改变的值。
例子:p标签中内容随input输入框中内容变化而变化
//数据劫持的实现
var input = document.querySelector('input')
var p = document.querySelector('p')
var btn = document.querySelector('.btn')
let obj = {
name:'小明',
age:50,
}
function Observe(origin,fn){
let target = {}
for(let key in origin){
Object.defineProperty(target,key,{
get(){
return origin[key]
},
set(val){
origin[key] = val
fn(target) //input事件
}
})
}
fn(target) //p中获取data.name事件
return target
}
let res = Observe(obj,(data)=>{
p.innerHTML = data.name
})
input.oninput = function(){
res.name = this.value
}
方法二语法:
Object.defineProperties是自己劫持到自己身上。
缺点:
后期动态通过点语法添加的成员 不能被监听的
Object.defineProperties(对象,{
key:配置,
})
//数据劫持的实现方法二:
let origin = {
name: "张三",
age: 18
}
for(var key in origin){
Object.defineProperties(origin,{
//复刻一份原始对象的属性
['_' + key]:{
value:origin[key],
writable:true,
},
[key]:{
get(){
return origin['_' + key]
},
set(val){
origin['_' + key] = val
}
}
})
}
origin.sex = 'nan'
console.log(origin); //{sex: 'nan', _name: '张三', _age: 18}
数据代理
Proxy
返回值就是你代理的结果
优点:
后期动态通过点语法添加的成员 也可以被监听的到
//数据代理
var input = document.querySelector('input')
var p = document.querySelector('p')
let obj = {
name:'小明',
age:33,
}
function Observe(obj,fn){
let target = new Proxy(obj,{
get(origin,property){
//property 表示每一个原始对象中的属性,默认遍历
return origin[property]
},
set(origin,property,val){
origin[property] = val
fn(target)
return true
}
})
fn(target)
return target
}
let res = Observe(obj,(data)=>{
p.innerHTML = data.name
})
res.sex = 'nan'
console.log(res); //Proxy(Object) {name: '小明', age: 33, sex: 'nan'}
input.oninput = function(){
res.name = this.value
}
console.log(res); //Proxy(Object) {name: '小明', age: 33, sex: 'nan'}
let arr = [{id:1,name:'袜子'},{id:2,name:'手机'}]
let app = Observe(arr,(res)=>{
console.log(res) //Proxy(Array) {0: {…}, 1: {…}}
})
console.log(app) //Proxy(Array) {0: {…}, 1: {…}}