本篇只是我对尚硅谷张老师课程代码自己做的一个注释,只是一个学习笔记,所以要结合视频看才行啊
课程视频(看33和34节)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Document</title>
</head>
<body>
<script type="text/javascript" >
let data = { //定义变量data,然后把对象{name:'尚硅谷',address:'北京'}的内存地址存放进变量data中
name:'尚硅谷',
address:'北京'
}
//创建一个监视的实例对象,用于监视data中属性的变化
const obs = new Observer(data) //第1步,把变量data(里边存的是对象的地址)传递给构造函数,其实就是把对象{name:'尚硅谷',address:'北京'}的地址传递给构造函数
console.log(obs)
//准备一个vm实例对象
let vm = {}
//第4步,这里data的被修改了,也就是说它里边存放的不再是对象{name:'尚硅谷',address:'北京'}的内存地址了。
//但是get和set仍然可以通过obj操作对象{name:'尚硅谷',address:'北京'},这是由于闭包的原因。
vm._data = data = obs
function Observer(obj){ //第2步,把data赋值给参数obj,也就是参数obj和data指向相同的内存空间,就是对象{name:'尚硅谷',address:'北京'}的内存地址。
//汇总对象中所有的属性形成一个数组
const keys = Object.keys(obj)
//遍历
keys.forEach((k)=>{
Object.defineProperty(this,k,{
//第3步:闭包。obj是局部变量,它的作用域和生命周期都只限于Observer函数内部。
//当Observer函数执行完毕时,obj会被回收,但是它的引用还被get函数和set函数所持有,这就形成了一个闭包。
//所以,即使obj被回收了,你仍然可以通过get函数和set函数来访问和修改obj的值。
get(){
return obj[k]
},
set(val){
console.log(`${k}被改了,我要去解析模板,生成虚拟DOM.....我要开始忙了`)
obj[k] = val
}
})
})
}
/**
* 傻强对数据劫持的总结:
* 经过上边的一段操作后,最终的效果是这样的:
* 1,对象obs里,拥有“原来的data所指向的对象{name:'尚硅谷',address:'北京'}”中的所有属性。但,它的每一个属性都有get和set方法。
* 2,变量data已经不再指向原来的对象{name:'尚硅谷',address:'北京'}了。变量data和vm._data指向obs对象,所以当我们读写vm._data.name和data.name的时候,就是读写obs.name,obs对象中的get和set方法会被调用。
* 3,当obs中的get和set被调用的时候,会操作局部变量obj指向的对象,局部变量obj中存放的一直都是“原来的对象{name:'尚硅谷',address:'北京'}”的内存地址,虽然obj是局部参数,但由于闭包的原因,局部变量obj不会被释放,它一直存放着“原来的对象{name:'尚硅谷',address:'北京'}”的内存地址,所以可以修改原来的对象的属性值。
* 4,每当我们通过vm._data或变量data读写“原来的对象{name:'尚硅谷',address:'北京'}中的属性”都会经过set和get,所以叫做数据劫持!
* 5,数据劫持的目的就是在get和set中,加上一写代码通知vue,数据被修改了。
*/
</script>
</body>
</html>