js基础知识——数据劫持
一、数据劫持
- 将来我们在使用框架的时候(vue), 框架目前都支持一个 "数据驱动视图",完成数据驱动视图 需要借助 数据劫持帮助我们完成
- 以原始数据为基础, 对数据进行一份复刻, 复刻出来数据是不允许修改的, 值从原始数据里面获取
- 语法:
Object.defineProperty('哪一个对象', '属性', '配置项')
- 配置项:
- value: 这个属性对应的值
- writable: 该属性是否可以被重写, 默认是 false 不允许被修改
- enumerable: 该属性是否可以被枚举, 默认是 false 不能被枚举到
- get: 是一个函数, 叫做 getter 获取器, 可以决定当前属性的值, 不能与 value writable 同时出现
- set: 是一个函数, 叫做 setter 设置器, 当你需要修改这个属性的时候, 会触发该函数
const obj = {}
obj.name = '哈哈'
Object.defineProperty(obj,'age',{
enumerable: true,
get () {
console.log('访问age属性,这个函数内可以做很多事')
return 300
},
set (val) {
console.log('修改obj的age属性,触发setter,想要设置的值为:',val)
}
})
obj.age = 99
console.log(obj)
二、数据劫持与渲染页面
const box = document.querySelector('.box')
const box2 = document.querySelector('.box2')
const obj = {}
obj.name = '哈哈'
obj.age = 20
const res = {}
Object.defineProperty(res,'age', {
enumerable: true,
get () {
return obj.age
},
set (val) {
box.innerHTML = `res年龄:${val}`
obj.age = val
}
})
res.age = 555
box.innerHTML = `res年龄:${res.age}`
box2.innerHTML = `obj年龄:${obj.age}`
obj.age = 6
res.age = 2
三、封装数据劫持
const box = document.querySelector('.box')
const box2 = document.querySelector('.box2')
const obj = {}
obj.name = '哈哈'
obj.age = 20
function observer (origin,callback) {
const target = {}
for(let key in origin) {
Object.defineProperty(target,key, {
enumerable: true,
get () {
return origin[key]
},
set (val) {
origin[key] = val
callback(target)
}
})
}
return target
}
const newObj = observer(obj,fn)
function fn (res) {
box.innerHTML = `年龄:${res.age} ;名字:${res.name}:`
}
newObj.age = 2
newObj.name = '呵呵'
四、数据劫持升级版
- 升级版数据劫持语法:
Object.defineProperties('那个对象', '配置项')
const obj = {}
obj.age = 18
obj.name = '张三'
升级的基础版-----将数据劫持后的对象属性放在res对象中(可截取多个对象)
const res = {}
Object.defineProperties(res,{
age: {
get () {
return obj.age
},
set (val) {
box2.innerHTML = `res对象age属性:${val},name属性${res.name}`
obj.age = val
}
},
name: {
get () {
return obj.name
},
set (val) {
box2.innerHTML = `res对象age属性:${res.age},name属性${val}`
obj.name = val
}
}
})
const res = {}
for (let key in obj) {
Object.defineProperties(res,{
[key]: {
get () {
return obj.[key]
},
set (val) {
obj[key] = val
box2.innerHTML = `res对象age属性:${val},name属性${res.name}`
}
},
})
}
box1.innerHTML = `obj对象age属性:${obj.age},name属性${obj.name}`
box2.innerHTML = `res对象age属性:${res.age},name属性${res.name}`
obj.age = 55
obj.name = 'liu'
res.age = 666
res.name = '王五'
for (let key in obj) {
Object.defineProperties(obj,{
['_' + key]:{
value:obj[key],
writable:true
},
[key]: {
get () {
return obj['_' + key]
},
set (val) {
obj['_' + key] = val
box1.innerHTML = `obj对象age属性:${obj.age},name属性${obj.name}`
}
}
})
}
box1.innerHTML = `obj对象age属性:${obj.age},name属性${obj.name}`
obj.age = 111
obj.name = 'pp'